NetworkManagementService.java revision 7244c977ecbc1f73e4cfd9d824fc2b68aa886139
1873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat/* 2873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat * Copyright (C) 2007 The Android Open Source Project 3873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat * 4873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat * Licensed under the Apache License, Version 2.0 (the "License"); 5873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat * you may not use this file except in compliance with the License. 6873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat * You may obtain a copy of the License at 7873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat * 8873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat * http://www.apache.org/licenses/LICENSE-2.0 9873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat * 10873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat * Unless required by applicable law or agreed to in writing, software 11873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat * distributed under the License is distributed on an "AS IS" BASIS, 12873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat * See the License for the specific language governing permissions and 14873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat * limitations under the License. 15873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat */ 16873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 17873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehatpackage com.android.server; 18873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 19350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkeyimport static android.Manifest.permission.MANAGE_NETWORK_POLICY; 201b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkeyimport static android.net.NetworkStats.IFACE_ALL; 211b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkeyimport static android.net.NetworkStats.TAG_NONE; 221b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkeyimport static android.net.NetworkStats.UID_ALL; 23350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkeyimport static android.provider.Settings.Secure.NETSTATS_ENABLED; 24a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkeyimport static com.android.server.NetworkManagementSocketTagger.PROP_QTAGUID_ENABLED; 25a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkeyimport static com.android.server.NetworkManagementSocketTagger.kernelToTag; 261b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey 27873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehatimport android.content.Context; 28873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehatimport android.content.pm.PackageManager; 294d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehatimport android.net.INetworkManagementEventObserver; 30eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkeyimport android.net.InterfaceConfiguration; 31ed1264093234b1f1354cd5f669eb82a50bb56869Robert Greenwaltimport android.net.LinkAddress; 32eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkeyimport android.net.NetworkStats; 33ed1264093234b1f1354cd5f669eb82a50bb56869Robert Greenwaltimport android.net.NetworkUtils; 3459b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwaltimport android.net.RouteInfo; 359ab518ad793385f8405edf19363fe825fb64f5f8Irfan Sheriffimport android.net.wifi.WifiConfiguration; 369ab518ad793385f8405edf19363fe825fb64f5f8Irfan Sheriffimport android.net.wifi.WifiConfiguration.KeyMgmt; 37eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkeyimport android.os.Binder; 38873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehatimport android.os.INetworkManagementService; 399a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkeyimport android.os.SystemClock; 4062dbb22bd4878369975492c8a1c234840e418a4fMarco Nelissenimport android.os.SystemProperties; 41350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkeyimport android.provider.Settings; 429ab518ad793385f8405edf19363fe825fb64f5f8Irfan Sheriffimport android.util.Log; 438a9b22056b13477f59df934928c00c58b5871c95Joe Onoratoimport android.util.Slog; 44b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkeyimport android.util.SparseBooleanArray; 45873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 464414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkeyimport com.google.android.collect.Lists; 474414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkeyimport com.google.android.collect.Maps; 48b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkeyimport com.google.android.collect.Sets; 494414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey 5059b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwaltimport java.io.BufferedReader; 5159b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwaltimport java.io.DataInputStream; 52873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehatimport java.io.File; 539a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkeyimport java.io.FileInputStream; 541b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkeyimport java.io.FileReader; 559a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkeyimport java.io.IOException; 569a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkeyimport java.io.InputStreamReader; 5759b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwaltimport java.net.Inet4Address; 58eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkeyimport java.net.InetAddress; 59eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkeyimport java.util.ArrayList; 604414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkeyimport java.util.HashMap; 61b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkeyimport java.util.HashSet; 62eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkeyimport java.util.NoSuchElementException; 63eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkeyimport java.util.StringTokenizer; 64e5c3afb29241fd3faae309f973645d7f6a7ed111Robert Greenwaltimport java.util.concurrent.CountDownLatch; 65873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 669a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkeyimport libcore.io.IoUtils; 679a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey 68873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat/** 69873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat * @hide 70873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat */ 71873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehatclass NetworkManagementService extends INetworkManagementService.Stub { 72eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey private static final String TAG = "NetworkManagementService"; 73cef65eeb0315c3118bf8860d6f723cb49ff6bc52Dianne Hackborn private static final boolean DBG = false; 74305bcbf0c961840c4505770d084a1caacc074dbbKenny Root private static final String NETD_TAG = "NetdConnector"; 75305bcbf0c961840c4505770d084a1caacc074dbbKenny Root 7659b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt private static final int ADD = 1; 7759b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt private static final int REMOVE = 2; 7859b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt 794414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey /** Path to {@code /proc/uid_stat}. */ 801b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey @Deprecated 81fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey private final File mStatsUid; 82fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey /** Path to {@code /proc/net/dev}. */ 83fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey private final File mStatsIface; 844414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey /** Path to {@code /proc/net/xt_qtaguid/stats}. */ 85fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey private final File mStatsXtUid; 86fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey /** Path to {@code /proc/net/xt_qtaguid/iface_stat}. */ 87fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey private final File mStatsXtIface; 884414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey 89fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey /** {@link #mStatsXtUid} headers. */ 904414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey private static final String KEY_IFACE = "iface"; 914414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey private static final String KEY_TAG_HEX = "acct_tag_hex"; 924414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey private static final String KEY_UID = "uid_tag_int"; 93a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey private static final String KEY_RX_BYTES = "rx_bytes"; 94a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey private static final String KEY_RX_PACKETS = "rx_packets"; 95a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey private static final String KEY_TX_BYTES = "tx_bytes"; 96a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey private static final String KEY_TX_PACKETS = "tx_packets"; 97eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey 98873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat class NetdResponseCode { 9912b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall /* Keep in sync with system/netd/ResponseCode.h */ 100873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat public static final int InterfaceListResult = 110; 101873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat public static final int TetherInterfaceListResult = 111; 102873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat public static final int TetherDnsFwdTgtListResult = 112; 10372759df749bb8557269db86c2e3b2a8a0343cc26San Mehat public static final int TtyListResult = 113; 104873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 105873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat public static final int TetherStatusResult = 210; 106873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat public static final int IpFwdStatusResult = 211; 107ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat public static final int InterfaceGetCfgResult = 213; 108e325392c257a5460de6327420c81729f4e687881Robert Greenwalt public static final int SoftapStatusResult = 214; 10991cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat public static final int InterfaceRxCounterResult = 216; 11091cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat public static final int InterfaceTxCounterResult = 217; 11191cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat public static final int InterfaceRxThrottleResult = 218; 11291cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat public static final int InterfaceTxThrottleResult = 219; 113e325392c257a5460de6327420c81729f4e687881Robert Greenwalt 114e325392c257a5460de6327420c81729f4e687881Robert Greenwalt public static final int InterfaceChange = 600; 11512b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall public static final int BandwidthControl = 601; 116873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 117873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 118873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat /** 119873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat * Binder context for this service 120873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat */ 121873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat private Context mContext; 122873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 123873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat /** 124873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat * connector object for communicating with netd 125873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat */ 126873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat private NativeDaemonConnector mConnector; 127873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 128e5c3afb29241fd3faae309f973645d7f6a7ed111Robert Greenwalt private Thread mThread; 129e5c3afb29241fd3faae309f973645d7f6a7ed111Robert Greenwalt private final CountDownLatch mConnectedSignal = new CountDownLatch(1); 130e5c3afb29241fd3faae309f973645d7f6a7ed111Robert Greenwalt 13141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey // TODO: replace with RemoteCallbackList 1324d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat private ArrayList<INetworkManagementEventObserver> mObservers; 1334d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat 13441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey private Object mQuotaLock = new Object(); 135b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey /** Set of interfaces with active quotas. */ 13641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey private HashSet<String> mActiveQuotaIfaces = Sets.newHashSet(); 13741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey /** Set of interfaces with active alerts. */ 13841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey private HashSet<String> mActiveAlertIfaces = Sets.newHashSet(); 139b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey /** Set of UIDs with active reject rules. */ 140b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey private SparseBooleanArray mUidRejectOnQuota = new SparseBooleanArray(); 141b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey 142350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey private boolean mBandwidthControlEnabled; 143350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey 144873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat /** 145873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat * Constructs a new NetworkManagementService instance 146873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat * 147873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat * @param context Binder context for this service 148873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat */ 1494414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey private NetworkManagementService(Context context, File procRoot) { 150873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat mContext = context; 1514d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat mObservers = new ArrayList<INetworkManagementEventObserver>(); 1524d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat 153fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey mStatsUid = new File(procRoot, "uid_stat"); 154fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey mStatsIface = new File(procRoot, "net/dev"); 155fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey mStatsXtUid = new File(procRoot, "net/xt_qtaguid/stats"); 156fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey mStatsXtIface = new File(procRoot, "net/xt_qtaguid/iface_stat"); 1574414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey 15862dbb22bd4878369975492c8a1c234840e418a4fMarco Nelissen if ("simulator".equals(SystemProperties.get("ro.product.device"))) { 15962dbb22bd4878369975492c8a1c234840e418a4fMarco Nelissen return; 16062dbb22bd4878369975492c8a1c234840e418a4fMarco Nelissen } 16162dbb22bd4878369975492c8a1c234840e418a4fMarco Nelissen 162873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat mConnector = new NativeDaemonConnector( 163305bcbf0c961840c4505770d084a1caacc074dbbKenny Root new NetdCallbackReceiver(), "netd", 10, NETD_TAG); 164e5c3afb29241fd3faae309f973645d7f6a7ed111Robert Greenwalt mThread = new Thread(mConnector, NETD_TAG); 165e5c3afb29241fd3faae309f973645d7f6a7ed111Robert Greenwalt } 166e5c3afb29241fd3faae309f973645d7f6a7ed111Robert Greenwalt 167e5c3afb29241fd3faae309f973645d7f6a7ed111Robert Greenwalt public static NetworkManagementService create(Context context) throws InterruptedException { 1684414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey NetworkManagementService service = new NetworkManagementService( 1694414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey context, new File("/proc/")); 170e5c3afb29241fd3faae309f973645d7f6a7ed111Robert Greenwalt if (DBG) Slog.d(TAG, "Creating NetworkManagementService"); 171e5c3afb29241fd3faae309f973645d7f6a7ed111Robert Greenwalt service.mThread.start(); 172e5c3afb29241fd3faae309f973645d7f6a7ed111Robert Greenwalt if (DBG) Slog.d(TAG, "Awaiting socket connection"); 173e5c3afb29241fd3faae309f973645d7f6a7ed111Robert Greenwalt service.mConnectedSignal.await(); 174e5c3afb29241fd3faae309f973645d7f6a7ed111Robert Greenwalt if (DBG) Slog.d(TAG, "Connected"); 175e5c3afb29241fd3faae309f973645d7f6a7ed111Robert Greenwalt return service; 176873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 177873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 1784414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey // @VisibleForTesting 179fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey public static NetworkManagementService createForTest( 180fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey Context context, File procRoot, boolean bandwidthControlEnabled) { 1814414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey // TODO: eventually connect with mock netd 182fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey final NetworkManagementService service = new NetworkManagementService(context, procRoot); 183fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey service.mBandwidthControlEnabled = bandwidthControlEnabled; 184fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey return service; 1854414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey } 1864414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey 187350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey public void systemReady() { 188350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey 189350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey // only enable bandwidth control when support exists, and requested by 190350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey // system setting. 191350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey final boolean hasKernelSupport = new File("/proc/net/xt_qtaguid/ctrl").exists(); 192350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey final boolean shouldEnable = 19305355c3eb69ef2cd8d08260be059be006a2883b9Jeff Sharkey Settings.Secure.getInt(mContext.getContentResolver(), NETSTATS_ENABLED, 1) != 0; 194350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey 195350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey mBandwidthControlEnabled = false; 196350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey if (hasKernelSupport && shouldEnable) { 197350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey Slog.d(TAG, "enabling bandwidth control"); 198350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey try { 199350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey mConnector.doCommand("bandwidth enable"); 200350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey mBandwidthControlEnabled = true; 201350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey } catch (NativeDaemonConnectorException e) { 202350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey Slog.e(TAG, "problem enabling bandwidth controls", e); 203350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey } 204350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey } else { 205350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey Slog.d(TAG, "not enabling bandwidth control"); 206350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey } 20762a2c8fed9cc74e9fa03871e0022205560a681a1Jeff Sharkey 208a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey SystemProperties.set(PROP_QTAGUID_ENABLED, mBandwidthControlEnabled ? "1" : "0"); 209350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey } 210350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey 2114d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat public void registerObserver(INetworkManagementEventObserver obs) { 2128a9b22056b13477f59df934928c00c58b5871c95Joe Onorato Slog.d(TAG, "Registering observer"); 2134d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat mObservers.add(obs); 2144d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat } 2154d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat 2164d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat public void unregisterObserver(INetworkManagementEventObserver obs) { 2178a9b22056b13477f59df934928c00c58b5871c95Joe Onorato Slog.d(TAG, "Unregistering observer"); 2184d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat mObservers.remove(mObservers.indexOf(obs)); 2194d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat } 2204d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat 2214d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat /** 2226143f5f7392fb0d3e5702a46a2415bd0ecb6efb4Mike J. Chen * Notify our observers of an interface status change 2234d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat */ 2246143f5f7392fb0d3e5702a46a2415bd0ecb6efb4Mike J. Chen private void notifyInterfaceStatusChanged(String iface, boolean up) { 2254d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat for (INetworkManagementEventObserver obs : mObservers) { 2264d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat try { 2276143f5f7392fb0d3e5702a46a2415bd0ecb6efb4Mike J. Chen obs.interfaceStatusChanged(iface, up); 2286143f5f7392fb0d3e5702a46a2415bd0ecb6efb4Mike J. Chen } catch (Exception ex) { 2296143f5f7392fb0d3e5702a46a2415bd0ecb6efb4Mike J. Chen Slog.w(TAG, "Observer notifier failed", ex); 2306143f5f7392fb0d3e5702a46a2415bd0ecb6efb4Mike J. Chen } 2316143f5f7392fb0d3e5702a46a2415bd0ecb6efb4Mike J. Chen } 2326143f5f7392fb0d3e5702a46a2415bd0ecb6efb4Mike J. Chen } 2336143f5f7392fb0d3e5702a46a2415bd0ecb6efb4Mike J. Chen 2346143f5f7392fb0d3e5702a46a2415bd0ecb6efb4Mike J. Chen /** 235f59c7d0f2ac8d489b6d8118543a57ea4a603eacfMike J. Chen * Notify our observers of an interface link state change 2366143f5f7392fb0d3e5702a46a2415bd0ecb6efb4Mike J. Chen * (typically, an Ethernet cable has been plugged-in or unplugged). 2376143f5f7392fb0d3e5702a46a2415bd0ecb6efb4Mike J. Chen */ 2386143f5f7392fb0d3e5702a46a2415bd0ecb6efb4Mike J. Chen private void notifyInterfaceLinkStateChanged(String iface, boolean up) { 2396143f5f7392fb0d3e5702a46a2415bd0ecb6efb4Mike J. Chen for (INetworkManagementEventObserver obs : mObservers) { 2406143f5f7392fb0d3e5702a46a2415bd0ecb6efb4Mike J. Chen try { 2416143f5f7392fb0d3e5702a46a2415bd0ecb6efb4Mike J. Chen obs.interfaceLinkStateChanged(iface, up); 2424d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat } catch (Exception ex) { 2438a9b22056b13477f59df934928c00c58b5871c95Joe Onorato Slog.w(TAG, "Observer notifier failed", ex); 2444d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat } 2454d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat } 2464d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat } 2474d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat 2484d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat /** 2494d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat * Notify our observers of an interface addition. 2504d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat */ 2514d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat private void notifyInterfaceAdded(String iface) { 2524d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat for (INetworkManagementEventObserver obs : mObservers) { 2534d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat try { 2544d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat obs.interfaceAdded(iface); 2554d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat } catch (Exception ex) { 2568a9b22056b13477f59df934928c00c58b5871c95Joe Onorato Slog.w(TAG, "Observer notifier failed", ex); 2574d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat } 2584d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat } 2594d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat } 2604d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat 2614d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat /** 2624d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat * Notify our observers of an interface removal. 2634d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat */ 2644d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat private void notifyInterfaceRemoved(String iface) { 2654d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat for (INetworkManagementEventObserver obs : mObservers) { 2664d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat try { 2674d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat obs.interfaceRemoved(iface); 2684d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat } catch (Exception ex) { 2698a9b22056b13477f59df934928c00c58b5871c95Joe Onorato Slog.w(TAG, "Observer notifier failed", ex); 2704d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat } 2714d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat } 2724d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat } 2734d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat 274e5c3afb29241fd3faae309f973645d7f6a7ed111Robert Greenwalt /** 27512b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall * Notify our observers of a limit reached. 27612b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall */ 27712b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall private void notifyLimitReached(String limitName, String iface) { 27812b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall for (INetworkManagementEventObserver obs : mObservers) { 27912b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall try { 28012b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall obs.limitReached(limitName, iface); 28112b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall Slog.d(TAG, "Observer notified limit reached for " + limitName + " " + iface); 28212b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall } catch (Exception ex) { 28312b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall Slog.w(TAG, "Observer notifier failed", ex); 28412b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall } 28512b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall } 28612b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall } 28712b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall 28812b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall /** 289e5c3afb29241fd3faae309f973645d7f6a7ed111Robert Greenwalt * Let us know the daemon is connected 290e5c3afb29241fd3faae309f973645d7f6a7ed111Robert Greenwalt */ 291e5c3afb29241fd3faae309f973645d7f6a7ed111Robert Greenwalt protected void onConnected() { 292e5c3afb29241fd3faae309f973645d7f6a7ed111Robert Greenwalt if (DBG) Slog.d(TAG, "onConnected"); 293e5c3afb29241fd3faae309f973645d7f6a7ed111Robert Greenwalt mConnectedSignal.countDown(); 294e5c3afb29241fd3faae309f973645d7f6a7ed111Robert Greenwalt } 295e5c3afb29241fd3faae309f973645d7f6a7ed111Robert Greenwalt 2964d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat 297873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat // 298873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat // Netd Callback handling 299873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat // 300873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 301873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat class NetdCallbackReceiver implements INativeDaemonConnectorCallbacks { 302873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat public void onDaemonConnected() { 303e5c3afb29241fd3faae309f973645d7f6a7ed111Robert Greenwalt NetworkManagementService.this.onConnected(); 304873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat new Thread() { 305873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat public void run() { 306873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 307873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat }.start(); 308873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 309873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat public boolean onEvent(int code, String raw, String[] cooked) { 31012b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall switch (code) { 31112b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall case NetdResponseCode.InterfaceChange: 31212b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall /* 31312b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall * a network interface change occured 31412b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall * Format: "NNN Iface added <name>" 31512b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall * "NNN Iface removed <name>" 31612b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall * "NNN Iface changed <name> <up/down>" 31712b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall * "NNN Iface linkstatus <name> <up/down>" 31812b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall */ 31912b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall if (cooked.length < 4 || !cooked[1].equals("Iface")) { 32012b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall throw new IllegalStateException( 32112b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall String.format("Invalid event from daemon (%s)", raw)); 32212b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall } 32312b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall if (cooked[2].equals("added")) { 32412b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall notifyInterfaceAdded(cooked[3]); 32512b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall return true; 32612b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall } else if (cooked[2].equals("removed")) { 32712b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall notifyInterfaceRemoved(cooked[3]); 32812b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall return true; 32912b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall } else if (cooked[2].equals("changed") && cooked.length == 5) { 33012b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall notifyInterfaceStatusChanged(cooked[3], cooked[4].equals("up")); 33112b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall return true; 33212b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall } else if (cooked[2].equals("linkstate") && cooked.length == 5) { 33312b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall notifyInterfaceLinkStateChanged(cooked[3], cooked[4].equals("up")); 33412b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall return true; 33512b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall } 336e325392c257a5460de6327420c81729f4e687881Robert Greenwalt throw new IllegalStateException( 337e325392c257a5460de6327420c81729f4e687881Robert Greenwalt String.format("Invalid event from daemon (%s)", raw)); 33812b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall // break; 33912b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall case NetdResponseCode.BandwidthControl: 34012b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall /* 34112b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall * Bandwidth control needs some attention 34212b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall * Format: "NNN limit alert <alertName> <ifaceName>" 34312b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall */ 34412b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall if (cooked.length < 5 || !cooked[1].equals("limit")) { 34512b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall throw new IllegalStateException( 34612b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall String.format("Invalid event from daemon (%s)", raw)); 34712b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall } 34812b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall if (cooked[2].equals("alert")) { 34912b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall notifyLimitReached(cooked[3], cooked[4]); 35012b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall return true; 35112b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall } 35212b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall throw new IllegalStateException( 35312b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall String.format("Invalid event from daemon (%s)", raw)); 35412b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall // break; 35512b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall default: break; 356e325392c257a5460de6327420c81729f4e687881Robert Greenwalt } 357e325392c257a5460de6327420c81729f4e687881Robert Greenwalt return false; 358873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 359873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 360873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 361ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat 362873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat // 363873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat // INetworkManagementService members 364873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat // 365873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 366873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat public String[] listInterfaces() throws IllegalStateException { 367873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat mContext.enforceCallingOrSelfPermission( 368873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService"); 369873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 370a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root try { 371a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root return mConnector.doListCommand("interface list", NetdResponseCode.InterfaceListResult); 372a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } catch (NativeDaemonConnectorException e) { 373a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root throw new IllegalStateException( 374a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root "Cannot communicate with native daemon to list interfaces"); 375a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } 376ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat } 377ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat 378ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat public InterfaceConfiguration getInterfaceConfig(String iface) throws IllegalStateException { 379a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root String rsp; 380a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root try { 381a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root rsp = mConnector.doCommand("interface getcfg " + iface).get(0); 382a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } catch (NativeDaemonConnectorException e) { 383a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root throw new IllegalStateException( 384a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root "Cannot communicate with native daemon to get interface config"); 385a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } 3868a9b22056b13477f59df934928c00c58b5871c95Joe Onorato Slog.d(TAG, String.format("rsp <%s>", rsp)); 387ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat 3882d2afd13af94c2669eb464101dee3b17c8448110Robert Greenwalt // Rsp: 213 xx:xx:xx:xx:xx:xx yyy.yyy.yyy.yyy zzz [flag1 flag2 flag3] 389ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat StringTokenizer st = new StringTokenizer(rsp); 390ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat 391a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root InterfaceConfiguration cfg; 392ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat try { 393a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root try { 394a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root int code = Integer.parseInt(st.nextToken(" ")); 395a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root if (code != NetdResponseCode.InterfaceGetCfgResult) { 396a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root throw new IllegalStateException( 397a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root String.format("Expected code %d, but got %d", 398a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root NetdResponseCode.InterfaceGetCfgResult, code)); 399a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } 400a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } catch (NumberFormatException nfe) { 401ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat throw new IllegalStateException( 402a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root String.format("Invalid response from daemon (%s)", rsp)); 403ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat } 404ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat 405a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root cfg = new InterfaceConfiguration(); 406a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root cfg.hwAddr = st.nextToken(" "); 407ed1264093234b1f1354cd5f669eb82a50bb56869Robert Greenwalt InetAddress addr = null; 4082d2afd13af94c2669eb464101dee3b17c8448110Robert Greenwalt int prefixLength = 0; 409a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root try { 410e590373ea71251cfffc8f22f011e2e6335dce716Robert Greenwalt addr = NetworkUtils.numericToInetAddress(st.nextToken(" ")); 411e590373ea71251cfffc8f22f011e2e6335dce716Robert Greenwalt } catch (IllegalArgumentException iae) { 412e590373ea71251cfffc8f22f011e2e6335dce716Robert Greenwalt Slog.e(TAG, "Failed to parse ipaddr", iae); 413a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } 414ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat 415a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root try { 4162d2afd13af94c2669eb464101dee3b17c8448110Robert Greenwalt prefixLength = Integer.parseInt(st.nextToken(" ")); 4172d2afd13af94c2669eb464101dee3b17c8448110Robert Greenwalt } catch (NumberFormatException nfe) { 4182d2afd13af94c2669eb464101dee3b17c8448110Robert Greenwalt Slog.e(TAG, "Failed to parse prefixLength", nfe); 419a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } 42004808c294027f8bc318643a94c85a999257d7f52Robert Greenwalt 4212d2afd13af94c2669eb464101dee3b17c8448110Robert Greenwalt cfg.addr = new LinkAddress(addr, prefixLength); 422a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root cfg.interfaceFlags = st.nextToken("]").trim() +"]"; 423a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } catch (NoSuchElementException nsee) { 424a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root throw new IllegalStateException( 425a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root String.format("Invalid response from daemon (%s)", rsp)); 426ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat } 4278a9b22056b13477f59df934928c00c58b5871c95Joe Onorato Slog.d(TAG, String.format("flags <%s>", cfg.interfaceFlags)); 428ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat return cfg; 429ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat } 430ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat 431ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat public void setInterfaceConfig( 432ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat String iface, InterfaceConfiguration cfg) throws IllegalStateException { 433ed1264093234b1f1354cd5f669eb82a50bb56869Robert Greenwalt LinkAddress linkAddr = cfg.addr; 4342d2afd13af94c2669eb464101dee3b17c8448110Robert Greenwalt if (linkAddr == null || linkAddr.getAddress() == null) { 4352d2afd13af94c2669eb464101dee3b17c8448110Robert Greenwalt throw new IllegalStateException("Null LinkAddress given"); 436ed1264093234b1f1354cd5f669eb82a50bb56869Robert Greenwalt } 4372d2afd13af94c2669eb464101dee3b17c8448110Robert Greenwalt String cmd = String.format("interface setcfg %s %s %d %s", iface, 4382d2afd13af94c2669eb464101dee3b17c8448110Robert Greenwalt linkAddr.getAddress().getHostAddress(), 4392d2afd13af94c2669eb464101dee3b17c8448110Robert Greenwalt linkAddr.getNetworkPrefixLength(), 4402d2afd13af94c2669eb464101dee3b17c8448110Robert Greenwalt cfg.interfaceFlags); 441a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root try { 442a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root mConnector.doCommand(cmd); 443a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } catch (NativeDaemonConnectorException e) { 444a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root throw new IllegalStateException( 44581d5ad515a9379432b2907aa9bcc830303202c84Robert Greenwalt "Unable to communicate with native daemon to interface setcfg - " + e); 446a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } 447873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 448873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 4497244c977ecbc1f73e4cfd9d824fc2b68aa886139Irfan Sheriff public void setInterfaceDown(String iface) throws IllegalStateException { 4507244c977ecbc1f73e4cfd9d824fc2b68aa886139Irfan Sheriff try { 4517244c977ecbc1f73e4cfd9d824fc2b68aa886139Irfan Sheriff InterfaceConfiguration ifcg = getInterfaceConfig(iface); 4527244c977ecbc1f73e4cfd9d824fc2b68aa886139Irfan Sheriff ifcg.interfaceFlags = ifcg.interfaceFlags.replace("up", "down"); 4537244c977ecbc1f73e4cfd9d824fc2b68aa886139Irfan Sheriff setInterfaceConfig(iface, ifcg); 4547244c977ecbc1f73e4cfd9d824fc2b68aa886139Irfan Sheriff } catch (NativeDaemonConnectorException e) { 4557244c977ecbc1f73e4cfd9d824fc2b68aa886139Irfan Sheriff throw new IllegalStateException( 4567244c977ecbc1f73e4cfd9d824fc2b68aa886139Irfan Sheriff "Unable to communicate with native daemon for interface down - " + e); 4577244c977ecbc1f73e4cfd9d824fc2b68aa886139Irfan Sheriff } 4587244c977ecbc1f73e4cfd9d824fc2b68aa886139Irfan Sheriff } 4597244c977ecbc1f73e4cfd9d824fc2b68aa886139Irfan Sheriff 4607244c977ecbc1f73e4cfd9d824fc2b68aa886139Irfan Sheriff public void setInterfaceUp(String iface) throws IllegalStateException { 4617244c977ecbc1f73e4cfd9d824fc2b68aa886139Irfan Sheriff try { 4627244c977ecbc1f73e4cfd9d824fc2b68aa886139Irfan Sheriff InterfaceConfiguration ifcg = getInterfaceConfig(iface); 4637244c977ecbc1f73e4cfd9d824fc2b68aa886139Irfan Sheriff ifcg.interfaceFlags = ifcg.interfaceFlags.replace("down", "up"); 4647244c977ecbc1f73e4cfd9d824fc2b68aa886139Irfan Sheriff setInterfaceConfig(iface, ifcg); 4657244c977ecbc1f73e4cfd9d824fc2b68aa886139Irfan Sheriff } catch (NativeDaemonConnectorException e) { 4667244c977ecbc1f73e4cfd9d824fc2b68aa886139Irfan Sheriff throw new IllegalStateException( 4677244c977ecbc1f73e4cfd9d824fc2b68aa886139Irfan Sheriff "Unable to communicate with native daemon for interface up - " + e); 4687244c977ecbc1f73e4cfd9d824fc2b68aa886139Irfan Sheriff } 4697244c977ecbc1f73e4cfd9d824fc2b68aa886139Irfan Sheriff } 4707244c977ecbc1f73e4cfd9d824fc2b68aa886139Irfan Sheriff 471f5600618df153d9c51388562ebf3524e3bdc8b7dIrfan Sheriff /* TODO: This is right now a IPv4 only function. Works for wifi which loses its 472f5600618df153d9c51388562ebf3524e3bdc8b7dIrfan Sheriff IPv6 addresses on interface down, but we need to do full clean up here */ 473f5600618df153d9c51388562ebf3524e3bdc8b7dIrfan Sheriff public void clearInterfaceAddresses(String iface) throws IllegalStateException { 474f5600618df153d9c51388562ebf3524e3bdc8b7dIrfan Sheriff String cmd = String.format("interface clearaddrs %s", iface); 475f5600618df153d9c51388562ebf3524e3bdc8b7dIrfan Sheriff try { 476f5600618df153d9c51388562ebf3524e3bdc8b7dIrfan Sheriff mConnector.doCommand(cmd); 477f5600618df153d9c51388562ebf3524e3bdc8b7dIrfan Sheriff } catch (NativeDaemonConnectorException e) { 478f5600618df153d9c51388562ebf3524e3bdc8b7dIrfan Sheriff throw new IllegalStateException( 479f5600618df153d9c51388562ebf3524e3bdc8b7dIrfan Sheriff "Unable to communicate with native daemon to interface clearallips - " + e); 480f5600618df153d9c51388562ebf3524e3bdc8b7dIrfan Sheriff } 481f5600618df153d9c51388562ebf3524e3bdc8b7dIrfan Sheriff } 482f5600618df153d9c51388562ebf3524e3bdc8b7dIrfan Sheriff 48359b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt public void addRoute(String interfaceName, RouteInfo route) { 48459b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt modifyRoute(interfaceName, ADD, route); 48559b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt } 48659b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt 48759b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt public void removeRoute(String interfaceName, RouteInfo route) { 48859b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt modifyRoute(interfaceName, REMOVE, route); 48959b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt } 49059b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt 49159b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt private void modifyRoute(String interfaceName, int action, RouteInfo route) { 49259b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt ArrayList<String> rsp; 49359b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt 49459b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt StringBuilder cmd; 49559b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt 49659b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt switch (action) { 49759b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt case ADD: 49859b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt { 49959b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt cmd = new StringBuilder("interface route add " + interfaceName); 50059b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt break; 50159b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt } 50259b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt case REMOVE: 50359b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt { 50459b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt cmd = new StringBuilder("interface route remove " + interfaceName); 50559b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt break; 50659b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt } 50759b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt default: 50859b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt throw new IllegalStateException("Unknown action type " + action); 50959b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt } 51059b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt 51159b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt // create triplet: dest-ip-addr prefixlength gateway-ip-addr 51259b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt LinkAddress la = route.getDestination(); 51359b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt cmd.append(' '); 51459b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt cmd.append(la.getAddress().getHostAddress()); 51559b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt cmd.append(' '); 51659b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt cmd.append(la.getNetworkPrefixLength()); 51759b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt cmd.append(' '); 51859b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt if (route.getGateway() == null) { 51959b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt if (la.getAddress() instanceof Inet4Address) { 52059b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt cmd.append("0.0.0.0"); 52159b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt } else { 52259b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt cmd.append ("::0"); 52359b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt } 52459b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt } else { 52559b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt cmd.append(route.getGateway().getHostAddress()); 52659b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt } 52759b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt try { 52859b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt rsp = mConnector.doCommand(cmd.toString()); 52959b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt } catch (NativeDaemonConnectorException e) { 53059b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt throw new IllegalStateException( 53159b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt "Unable to communicate with native dameon to add routes - " 53259b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt + e); 53359b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt } 53459b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt 53559b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt for (String line : rsp) { 53659b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt Log.v(TAG, "add route response is " + line); 53759b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt } 53859b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt } 53959b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt 54059b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt private ArrayList<String> readRouteList(String filename) { 54159b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt FileInputStream fstream = null; 54259b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt ArrayList<String> list = new ArrayList<String>(); 54359b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt 54459b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt try { 54559b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt fstream = new FileInputStream(filename); 54659b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt DataInputStream in = new DataInputStream(fstream); 54759b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt BufferedReader br = new BufferedReader(new InputStreamReader(in)); 54859b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt String s; 54959b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt 55059b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt // throw away the title line 55159b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt 55259b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt while (((s = br.readLine()) != null) && (s.length() != 0)) { 55359b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt list.add(s); 55459b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt } 55559b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt } catch (IOException ex) { 55659b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt // return current list, possibly empty 55759b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt } finally { 55859b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt if (fstream != null) { 55959b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt try { 56059b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt fstream.close(); 56159b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt } catch (IOException ex) {} 56259b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt } 56359b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt } 56459b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt 56559b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt return list; 56659b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt } 56759b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt 56859b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt public RouteInfo[] getRoutes(String interfaceName) { 56959b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt ArrayList<RouteInfo> routes = new ArrayList<RouteInfo>(); 57059b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt 57159b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt // v4 routes listed as: 57259b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt // iface dest-addr gateway-addr flags refcnt use metric netmask mtu window IRTT 57359b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt for (String s : readRouteList("/proc/net/route")) { 57459b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt String[] fields = s.split("\t"); 57559b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt 57659b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt if (fields.length > 7) { 57759b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt String iface = fields[0]; 57859b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt 57959b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt if (interfaceName.equals(iface)) { 58059b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt String dest = fields[1]; 58159b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt String gate = fields[2]; 58259b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt String flags = fields[3]; // future use? 58359b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt String mask = fields[7]; 58459b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt try { 58559b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt // address stored as a hex string, ex: 0014A8C0 58659b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt InetAddress destAddr = 58759b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt NetworkUtils.intToInetAddress((int)Long.parseLong(dest, 16)); 58859b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt int prefixLength = 58959b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt NetworkUtils.netmaskIntToPrefixLength( 59059b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt (int)Long.parseLong(mask, 16)); 59159b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt LinkAddress linkAddress = new LinkAddress(destAddr, prefixLength); 59259b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt 59359b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt // address stored as a hex string, ex 0014A8C0 59459b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt InetAddress gatewayAddr = 59559b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt NetworkUtils.intToInetAddress((int)Long.parseLong(gate, 16)); 59659b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt 59759b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt RouteInfo route = new RouteInfo(linkAddress, gatewayAddr); 59859b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt routes.add(route); 59959b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt } catch (Exception e) { 60059b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt Log.e(TAG, "Error parsing route " + s + " : " + e); 60159b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt continue; 60259b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt } 60359b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt } 60459b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt } 60559b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt } 60659b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt 60759b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt // v6 routes listed as: 60859b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt // dest-addr prefixlength ?? ?? gateway-addr ?? ?? ?? ?? iface 60959b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt for (String s : readRouteList("/proc/net/ipv6_route")) { 61059b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt String[]fields = s.split("\\s+"); 61159b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt if (fields.length > 9) { 61259b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt String iface = fields[9].trim(); 61359b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt if (interfaceName.equals(iface)) { 61459b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt String dest = fields[0]; 61559b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt String prefix = fields[1]; 61659b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt String gate = fields[4]; 61759b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt 61859b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt try { 61959b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt // prefix length stored as a hex string, ex 40 62059b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt int prefixLength = Integer.parseInt(prefix, 16); 62159b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt 62259b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt // address stored as a 32 char hex string 62359b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt // ex fe800000000000000000000000000000 62459b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt InetAddress destAddr = NetworkUtils.hexToInet6Address(dest); 62559b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt LinkAddress linkAddress = new LinkAddress(destAddr, prefixLength); 62659b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt 62759b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt InetAddress gateAddr = NetworkUtils.hexToInet6Address(gate); 62859b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt 62959b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt RouteInfo route = new RouteInfo(linkAddress, gateAddr); 63059b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt routes.add(route); 63159b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt } catch (Exception e) { 63259b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt Log.e(TAG, "Error parsing route " + s + " : " + e); 63359b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt continue; 63459b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt } 63559b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt } 63659b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt } 63759b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt } 63859b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt return (RouteInfo[]) routes.toArray(new RouteInfo[0]); 63959b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt } 64059b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt 641873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat public void shutdown() { 642873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat if (mContext.checkCallingOrSelfPermission( 643873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat android.Manifest.permission.SHUTDOWN) 644873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat != PackageManager.PERMISSION_GRANTED) { 645873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat throw new SecurityException("Requires SHUTDOWN permission"); 646873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 647873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 6488a9b22056b13477f59df934928c00c58b5871c95Joe Onorato Slog.d(TAG, "Shutting down"); 649873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 650873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 651873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat public boolean getIpForwardingEnabled() throws IllegalStateException{ 652873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat mContext.enforceCallingOrSelfPermission( 653873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService"); 654873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 655a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root ArrayList<String> rsp; 656a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root try { 657a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root rsp = mConnector.doCommand("ipfwd status"); 658a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } catch (NativeDaemonConnectorException e) { 659a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root throw new IllegalStateException( 660a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root "Unable to communicate with native daemon to ipfwd status"); 661a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } 662873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 663873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat for (String line : rsp) { 664a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root String[] tok = line.split(" "); 665a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root if (tok.length < 3) { 666a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root Slog.e(TAG, "Malformed response from native daemon: " + line); 667a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root return false; 668a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } 669a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root 670873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat int code = Integer.parseInt(tok[0]); 671873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat if (code == NetdResponseCode.IpFwdStatusResult) { 672873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat // 211 Forwarding <enabled/disabled> 673a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root return "enabled".equals(tok[2]); 674873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } else { 675873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat throw new IllegalStateException(String.format("Unexpected response code %d", code)); 676873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 677873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 678873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat throw new IllegalStateException("Got an empty response"); 679873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 680873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 681873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat public void setIpForwardingEnabled(boolean enable) throws IllegalStateException { 682873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat mContext.enforceCallingOrSelfPermission( 683873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService"); 684873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat mConnector.doCommand(String.format("ipfwd %sable", (enable ? "en" : "dis"))); 685873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 686873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 687bfb7bfa53847832db2a3eb05e5eff7cb974c3c7aRobert Greenwalt public void startTethering(String[] dhcpRange) 688873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat throws IllegalStateException { 689873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat mContext.enforceCallingOrSelfPermission( 690873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService"); 691bfb7bfa53847832db2a3eb05e5eff7cb974c3c7aRobert Greenwalt // cmd is "tether start first_start first_stop second_start second_stop ..." 692bfb7bfa53847832db2a3eb05e5eff7cb974c3c7aRobert Greenwalt // an odd number of addrs will fail 693bfb7bfa53847832db2a3eb05e5eff7cb974c3c7aRobert Greenwalt String cmd = "tether start"; 694bfb7bfa53847832db2a3eb05e5eff7cb974c3c7aRobert Greenwalt for (String d : dhcpRange) { 695bfb7bfa53847832db2a3eb05e5eff7cb974c3c7aRobert Greenwalt cmd += " " + d; 696bfb7bfa53847832db2a3eb05e5eff7cb974c3c7aRobert Greenwalt } 697a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root 698a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root try { 699a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root mConnector.doCommand(cmd); 700a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } catch (NativeDaemonConnectorException e) { 701a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root throw new IllegalStateException("Unable to communicate to native daemon"); 702a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } 703873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 704873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 705873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat public void stopTethering() throws IllegalStateException { 706873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat mContext.enforceCallingOrSelfPermission( 707873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService"); 708a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root try { 709a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root mConnector.doCommand("tether stop"); 710a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } catch (NativeDaemonConnectorException e) { 711a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root throw new IllegalStateException("Unable to communicate to native daemon to stop tether"); 712a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } 713873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 714873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 715873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat public boolean isTetheringStarted() throws IllegalStateException { 716873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat mContext.enforceCallingOrSelfPermission( 717873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService"); 718873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 719a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root ArrayList<String> rsp; 720a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root try { 721a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root rsp = mConnector.doCommand("tether status"); 722a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } catch (NativeDaemonConnectorException e) { 723a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root throw new IllegalStateException( 724a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root "Unable to communicate to native daemon to get tether status"); 725a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } 726873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 727873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat for (String line : rsp) { 728a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root String[] tok = line.split(" "); 729a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root if (tok.length < 3) { 730a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root throw new IllegalStateException("Malformed response for tether status: " + line); 731a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } 732873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat int code = Integer.parseInt(tok[0]); 733873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat if (code == NetdResponseCode.TetherStatusResult) { 734873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat // XXX: Tethering services <started/stopped> <TBD>... 735a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root return "started".equals(tok[2]); 736873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } else { 737873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat throw new IllegalStateException(String.format("Unexpected response code %d", code)); 738873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 739873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 740873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat throw new IllegalStateException("Got an empty response"); 741873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 742873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 743873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat public void tetherInterface(String iface) throws IllegalStateException { 744873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat mContext.enforceCallingOrSelfPermission( 745873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService"); 746a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root try { 747a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root mConnector.doCommand("tether interface add " + iface); 748a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } catch (NativeDaemonConnectorException e) { 749a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root throw new IllegalStateException( 750a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root "Unable to communicate to native daemon for adding tether interface"); 751a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } 752873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 753873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 754873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat public void untetherInterface(String iface) { 755873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat mContext.enforceCallingOrSelfPermission( 756873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService"); 757a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root try { 758a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root mConnector.doCommand("tether interface remove " + iface); 759a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } catch (NativeDaemonConnectorException e) { 760a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root throw new IllegalStateException( 761a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root "Unable to communicate to native daemon for removing tether interface"); 762a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } 763873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 764873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 765873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat public String[] listTetheredInterfaces() throws IllegalStateException { 766873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat mContext.enforceCallingOrSelfPermission( 767873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService"); 768a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root try { 769a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root return mConnector.doListCommand( 770a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root "tether interface list", NetdResponseCode.TetherInterfaceListResult); 771a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } catch (NativeDaemonConnectorException e) { 772a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root throw new IllegalStateException( 773a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root "Unable to communicate to native daemon for listing tether interfaces"); 774a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } 775873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 776873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 777873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat public void setDnsForwarders(String[] dns) throws IllegalStateException { 778873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat mContext.enforceCallingOrSelfPermission( 779873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService"); 780873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat try { 781d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt String cmd = "tether dns set"; 782873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat for (String s : dns) { 783e590373ea71251cfffc8f22f011e2e6335dce716Robert Greenwalt cmd += " " + NetworkUtils.numericToInetAddress(s).getHostAddress(); 784873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 785a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root try { 786a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root mConnector.doCommand(cmd); 787a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } catch (NativeDaemonConnectorException e) { 788a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root throw new IllegalStateException( 789a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root "Unable to communicate to native daemon for setting tether dns"); 790a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } 791e590373ea71251cfffc8f22f011e2e6335dce716Robert Greenwalt } catch (IllegalArgumentException e) { 792873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat throw new IllegalStateException("Error resolving dns name", e); 793873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 794873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 795873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 796873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat public String[] getDnsForwarders() throws IllegalStateException { 797873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat mContext.enforceCallingOrSelfPermission( 798873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService"); 799a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root try { 800a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root return mConnector.doListCommand( 801a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root "tether dns list", NetdResponseCode.TetherDnsFwdTgtListResult); 802a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } catch (NativeDaemonConnectorException e) { 803a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root throw new IllegalStateException( 804a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root "Unable to communicate to native daemon for listing tether dns"); 805a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } 806873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 807873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 808873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat public void enableNat(String internalInterface, String externalInterface) 809873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat throws IllegalStateException { 810873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat mContext.enforceCallingOrSelfPermission( 811873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService"); 812a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root try { 813a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root mConnector.doCommand( 814a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root String.format("nat enable %s %s", internalInterface, externalInterface)); 815a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } catch (NativeDaemonConnectorException e) { 816a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root throw new IllegalStateException( 817a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root "Unable to communicate to native daemon for enabling NAT interface"); 818a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } 819873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 820873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat 821873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat public void disableNat(String internalInterface, String externalInterface) 822873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat throws IllegalStateException { 823873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat mContext.enforceCallingOrSelfPermission( 824873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService"); 825a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root try { 826a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root mConnector.doCommand( 827a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root String.format("nat disable %s %s", internalInterface, externalInterface)); 828a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } catch (NativeDaemonConnectorException e) { 829a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root throw new IllegalStateException( 830a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root "Unable to communicate to native daemon for disabling NAT interface"); 831a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } 832873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat } 83372759df749bb8557269db86c2e3b2a8a0343cc26San Mehat 83472759df749bb8557269db86c2e3b2a8a0343cc26San Mehat public String[] listTtys() throws IllegalStateException { 83572759df749bb8557269db86c2e3b2a8a0343cc26San Mehat mContext.enforceCallingOrSelfPermission( 83672759df749bb8557269db86c2e3b2a8a0343cc26San Mehat android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService"); 837a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root try { 838a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root return mConnector.doListCommand("list_ttys", NetdResponseCode.TtyListResult); 839a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } catch (NativeDaemonConnectorException e) { 840a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root throw new IllegalStateException( 841a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root "Unable to communicate to native daemon for listing TTYs"); 842a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } 84372759df749bb8557269db86c2e3b2a8a0343cc26San Mehat } 84472759df749bb8557269db86c2e3b2a8a0343cc26San Mehat 845d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt public void attachPppd(String tty, String localAddr, String remoteAddr, String dns1Addr, 846d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt String dns2Addr) throws IllegalStateException { 84772759df749bb8557269db86c2e3b2a8a0343cc26San Mehat try { 84872759df749bb8557269db86c2e3b2a8a0343cc26San Mehat mContext.enforceCallingOrSelfPermission( 84972759df749bb8557269db86c2e3b2a8a0343cc26San Mehat android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService"); 850d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt mConnector.doCommand(String.format("pppd attach %s %s %s %s %s", tty, 851e590373ea71251cfffc8f22f011e2e6335dce716Robert Greenwalt NetworkUtils.numericToInetAddress(localAddr).getHostAddress(), 852e590373ea71251cfffc8f22f011e2e6335dce716Robert Greenwalt NetworkUtils.numericToInetAddress(remoteAddr).getHostAddress(), 853e590373ea71251cfffc8f22f011e2e6335dce716Robert Greenwalt NetworkUtils.numericToInetAddress(dns1Addr).getHostAddress(), 854e590373ea71251cfffc8f22f011e2e6335dce716Robert Greenwalt NetworkUtils.numericToInetAddress(dns2Addr).getHostAddress())); 855e590373ea71251cfffc8f22f011e2e6335dce716Robert Greenwalt } catch (IllegalArgumentException e) { 85672759df749bb8557269db86c2e3b2a8a0343cc26San Mehat throw new IllegalStateException("Error resolving addr", e); 857a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } catch (NativeDaemonConnectorException e) { 858a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root throw new IllegalStateException("Error communicating to native daemon to attach pppd", e); 85972759df749bb8557269db86c2e3b2a8a0343cc26San Mehat } 86072759df749bb8557269db86c2e3b2a8a0343cc26San Mehat } 86172759df749bb8557269db86c2e3b2a8a0343cc26San Mehat 86272759df749bb8557269db86c2e3b2a8a0343cc26San Mehat public void detachPppd(String tty) throws IllegalStateException { 86372759df749bb8557269db86c2e3b2a8a0343cc26San Mehat mContext.enforceCallingOrSelfPermission( 86472759df749bb8557269db86c2e3b2a8a0343cc26San Mehat android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService"); 865a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root try { 866a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root mConnector.doCommand(String.format("pppd detach %s", tty)); 867a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } catch (NativeDaemonConnectorException e) { 868a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root throw new IllegalStateException("Error communicating to native daemon to detach pppd", e); 869a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } 87072759df749bb8557269db86c2e3b2a8a0343cc26San Mehat } 871ce1200d42c46ae5d3ec637587b07dfdc02ad21c0Robert Greenwalt 872c2f54c267b896cd1799d82be81e904a2b56c2f26Irfan Sheriff public void startAccessPoint(WifiConfiguration wifiConfig, String wlanIface, String softapIface) 8735321aef4a22daef6ed01ed48d936cdd82f2e38b7Irfan Sheriff throws IllegalStateException { 8745321aef4a22daef6ed01ed48d936cdd82f2e38b7Irfan Sheriff mContext.enforceCallingOrSelfPermission( 8755321aef4a22daef6ed01ed48d936cdd82f2e38b7Irfan Sheriff android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService"); 8765321aef4a22daef6ed01ed48d936cdd82f2e38b7Irfan Sheriff mContext.enforceCallingOrSelfPermission( 877c2f54c267b896cd1799d82be81e904a2b56c2f26Irfan Sheriff android.Manifest.permission.CHANGE_WIFI_STATE, "NetworkManagementService"); 878a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root try { 879cb30b22ff507a5a9a5d9c584f8b082f5e96c4d02Irfan Sheriff wifiFirmwareReload(wlanIface, "AP"); 880a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root mConnector.doCommand(String.format("softap start " + wlanIface)); 881a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root if (wifiConfig == null) { 882a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root mConnector.doCommand(String.format("softap set " + wlanIface + " " + softapIface)); 883a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } else { 884a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root /** 885a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root * softap set arg1 arg2 arg3 [arg4 arg5 arg6 arg7 arg8] 886a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root * argv1 - wlan interface 887a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root * argv2 - softap interface 888a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root * argv3 - SSID 889a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root * argv4 - Security 890a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root * argv5 - Key 891a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root * argv6 - Channel 892a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root * argv7 - Preamble 893a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root * argv8 - Max SCB 894a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root */ 895ec8d23af7372204f068aebaa1bfae87dc9260e23Irfan Sheriff String str = String.format("softap set " + wlanIface + " " + softapIface + 896ec8d23af7372204f068aebaa1bfae87dc9260e23Irfan Sheriff " %s %s %s", convertQuotedString(wifiConfig.SSID), 897ec8d23af7372204f068aebaa1bfae87dc9260e23Irfan Sheriff getSecurityType(wifiConfig), 898ec8d23af7372204f068aebaa1bfae87dc9260e23Irfan Sheriff convertQuotedString(wifiConfig.preSharedKey)); 899a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root mConnector.doCommand(str); 900a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } 901a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root mConnector.doCommand(String.format("softap startap")); 902a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } catch (NativeDaemonConnectorException e) { 903a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root throw new IllegalStateException("Error communicating to native daemon to start softap", e); 904a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } 9055321aef4a22daef6ed01ed48d936cdd82f2e38b7Irfan Sheriff } 9065321aef4a22daef6ed01ed48d936cdd82f2e38b7Irfan Sheriff 907a6e559edb73886c626e0e5a95085d0ead767ceb7Irfan Sheriff private String convertQuotedString(String s) { 9087baec0fe4ef66ac308ebc132d6c08865db653b30Irfan Sheriff if (s == null) { 9097baec0fe4ef66ac308ebc132d6c08865db653b30Irfan Sheriff return s; 9107baec0fe4ef66ac308ebc132d6c08865db653b30Irfan Sheriff } 9117baec0fe4ef66ac308ebc132d6c08865db653b30Irfan Sheriff /* Replace \ with \\, then " with \" and add quotes at end */ 9127baec0fe4ef66ac308ebc132d6c08865db653b30Irfan Sheriff return '"' + s.replaceAll("\\\\","\\\\\\\\").replaceAll("\"","\\\\\"") + '"'; 913a6e559edb73886c626e0e5a95085d0ead767ceb7Irfan Sheriff } 914a6e559edb73886c626e0e5a95085d0ead767ceb7Irfan Sheriff 915ec8d23af7372204f068aebaa1bfae87dc9260e23Irfan Sheriff private String getSecurityType(WifiConfiguration wifiConfig) { 916ec8d23af7372204f068aebaa1bfae87dc9260e23Irfan Sheriff switch (wifiConfig.getAuthType()) { 917ec8d23af7372204f068aebaa1bfae87dc9260e23Irfan Sheriff case KeyMgmt.WPA_PSK: 918ec8d23af7372204f068aebaa1bfae87dc9260e23Irfan Sheriff return "wpa-psk"; 919ec8d23af7372204f068aebaa1bfae87dc9260e23Irfan Sheriff case KeyMgmt.WPA2_PSK: 920ec8d23af7372204f068aebaa1bfae87dc9260e23Irfan Sheriff return "wpa2-psk"; 921ec8d23af7372204f068aebaa1bfae87dc9260e23Irfan Sheriff default: 922ec8d23af7372204f068aebaa1bfae87dc9260e23Irfan Sheriff return "open"; 923ec8d23af7372204f068aebaa1bfae87dc9260e23Irfan Sheriff } 924ec8d23af7372204f068aebaa1bfae87dc9260e23Irfan Sheriff } 925ec8d23af7372204f068aebaa1bfae87dc9260e23Irfan Sheriff 926cb30b22ff507a5a9a5d9c584f8b082f5e96c4d02Irfan Sheriff /* @param mode can be "AP", "STA" or "P2P" */ 927cb30b22ff507a5a9a5d9c584f8b082f5e96c4d02Irfan Sheriff public void wifiFirmwareReload(String wlanIface, String mode) throws IllegalStateException { 928cb30b22ff507a5a9a5d9c584f8b082f5e96c4d02Irfan Sheriff mContext.enforceCallingOrSelfPermission( 929cb30b22ff507a5a9a5d9c584f8b082f5e96c4d02Irfan Sheriff android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService"); 930cb30b22ff507a5a9a5d9c584f8b082f5e96c4d02Irfan Sheriff mContext.enforceCallingOrSelfPermission( 931cb30b22ff507a5a9a5d9c584f8b082f5e96c4d02Irfan Sheriff android.Manifest.permission.CHANGE_WIFI_STATE, "NetworkManagementService"); 932cb30b22ff507a5a9a5d9c584f8b082f5e96c4d02Irfan Sheriff 933cb30b22ff507a5a9a5d9c584f8b082f5e96c4d02Irfan Sheriff try { 934cb30b22ff507a5a9a5d9c584f8b082f5e96c4d02Irfan Sheriff mConnector.doCommand(String.format("softap fwreload " + wlanIface + " " + mode)); 935cb30b22ff507a5a9a5d9c584f8b082f5e96c4d02Irfan Sheriff } catch (NativeDaemonConnectorException e) { 936cb30b22ff507a5a9a5d9c584f8b082f5e96c4d02Irfan Sheriff throw new IllegalStateException("Error communicating to native daemon ", e); 937cb30b22ff507a5a9a5d9c584f8b082f5e96c4d02Irfan Sheriff } 938cb30b22ff507a5a9a5d9c584f8b082f5e96c4d02Irfan Sheriff } 939cb30b22ff507a5a9a5d9c584f8b082f5e96c4d02Irfan Sheriff 94023eb297c771bd996fe8559178feb1a07be43ad72Irfan Sheriff public void stopAccessPoint(String wlanIface) throws IllegalStateException { 9415321aef4a22daef6ed01ed48d936cdd82f2e38b7Irfan Sheriff mContext.enforceCallingOrSelfPermission( 9425321aef4a22daef6ed01ed48d936cdd82f2e38b7Irfan Sheriff android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService"); 9435321aef4a22daef6ed01ed48d936cdd82f2e38b7Irfan Sheriff mContext.enforceCallingOrSelfPermission( 944c2f54c267b896cd1799d82be81e904a2b56c2f26Irfan Sheriff android.Manifest.permission.CHANGE_WIFI_STATE, "NetworkManagementService"); 945a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root try { 946a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root mConnector.doCommand("softap stopap"); 94723eb297c771bd996fe8559178feb1a07be43ad72Irfan Sheriff mConnector.doCommand("softap stop " + wlanIface); 948cb30b22ff507a5a9a5d9c584f8b082f5e96c4d02Irfan Sheriff wifiFirmwareReload(wlanIface, "STA"); 949a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } catch (NativeDaemonConnectorException e) { 950a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root throw new IllegalStateException("Error communicating to native daemon to stop soft AP", 951a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root e); 952a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } 9535321aef4a22daef6ed01ed48d936cdd82f2e38b7Irfan Sheriff } 9545321aef4a22daef6ed01ed48d936cdd82f2e38b7Irfan Sheriff 955c2f54c267b896cd1799d82be81e904a2b56c2f26Irfan Sheriff public void setAccessPoint(WifiConfiguration wifiConfig, String wlanIface, String softapIface) 956c2f54c267b896cd1799d82be81e904a2b56c2f26Irfan Sheriff throws IllegalStateException { 957c2f54c267b896cd1799d82be81e904a2b56c2f26Irfan Sheriff mContext.enforceCallingOrSelfPermission( 958c2f54c267b896cd1799d82be81e904a2b56c2f26Irfan Sheriff android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService"); 959c2f54c267b896cd1799d82be81e904a2b56c2f26Irfan Sheriff mContext.enforceCallingOrSelfPermission( 960c2f54c267b896cd1799d82be81e904a2b56c2f26Irfan Sheriff android.Manifest.permission.CHANGE_WIFI_STATE, "NetworkManagementService"); 961a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root try { 962a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root if (wifiConfig == null) { 963a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root mConnector.doCommand(String.format("softap set " + wlanIface + " " + softapIface)); 964a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } else { 965a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root String str = String.format("softap set " + wlanIface + " " + softapIface 966a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root + " %s %s %s", convertQuotedString(wifiConfig.SSID), 967ec8d23af7372204f068aebaa1bfae87dc9260e23Irfan Sheriff getSecurityType(wifiConfig), 968a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root convertQuotedString(wifiConfig.preSharedKey)); 969a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root mConnector.doCommand(str); 970a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } 971a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } catch (NativeDaemonConnectorException e) { 972a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root throw new IllegalStateException("Error communicating to native daemon to set soft AP", 973a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root e); 974c2f54c267b896cd1799d82be81e904a2b56c2f26Irfan Sheriff } 975c2f54c267b896cd1799d82be81e904a2b56c2f26Irfan Sheriff } 97691cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat 97791cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat private long getInterfaceCounter(String iface, boolean rx) { 97891cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat mContext.enforceCallingOrSelfPermission( 97991cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService"); 98091cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat try { 981a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root String rsp; 982a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root try { 983a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root rsp = mConnector.doCommand( 984a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root String.format("interface read%scounter %s", (rx ? "rx" : "tx"), iface)).get(0); 985a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } catch (NativeDaemonConnectorException e1) { 986a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root Slog.e(TAG, "Error communicating with native daemon", e1); 987a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root return -1; 988a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } 989a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root 990a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root String[] tok = rsp.split(" "); 991a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root if (tok.length < 2) { 992a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root Slog.e(TAG, String.format("Malformed response for reading %s interface", 993a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root (rx ? "rx" : "tx"))); 994a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root return -1; 995a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } 996a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root 99791cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat int code; 99891cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat try { 99991cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat code = Integer.parseInt(tok[0]); 100091cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat } catch (NumberFormatException nfe) { 100191cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat Slog.e(TAG, String.format("Error parsing code %s", tok[0])); 100291cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat return -1; 100391cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat } 100491cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat if ((rx && code != NetdResponseCode.InterfaceRxCounterResult) || ( 100591cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat !rx && code != NetdResponseCode.InterfaceTxCounterResult)) { 100691cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat Slog.e(TAG, String.format("Unexpected response code %d", code)); 100791cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat return -1; 100891cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat } 100991cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat return Long.parseLong(tok[1]); 101091cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat } catch (Exception e) { 101191cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat Slog.e(TAG, String.format( 101291cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat "Failed to read interface %s counters", (rx ? "rx" : "tx")), e); 101391cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat } 101491cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat return -1; 101591cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat } 101691cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat 1017eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey @Override 10189a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey public NetworkStats getNetworkStatsSummary() { 10199a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey mContext.enforceCallingOrSelfPermission( 10209a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService"); 10219a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey 1022fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 6); 1023fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey final NetworkStats.Entry entry = new NetworkStats.Entry(); 1024fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey 1025fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey final HashSet<String> activeIfaces = Sets.newHashSet(); 1026fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey final ArrayList<String> values = Lists.newArrayList(); 1027fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey 1028fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey BufferedReader reader = null; 1029fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey try { 1030fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey reader = new BufferedReader(new FileReader(mStatsIface)); 1031fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey 1032fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey // skip first two header lines 1033fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey reader.readLine(); 1034fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey reader.readLine(); 1035fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey 1036fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey // parse remaining lines 1037fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey String line; 1038fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey while ((line = reader.readLine()) != null) { 1039fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey splitLine(line, values); 1040fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey 1041fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey try { 1042fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey entry.iface = values.get(0); 1043fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey entry.uid = UID_ALL; 1044fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey entry.tag = TAG_NONE; 1045fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey entry.rxBytes = Long.parseLong(values.get(1)); 1046fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey entry.rxPackets = Long.parseLong(values.get(2)); 1047fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey entry.txBytes = Long.parseLong(values.get(9)); 1048fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey entry.txPackets = Long.parseLong(values.get(10)); 1049fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey 1050fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey activeIfaces.add(entry.iface); 1051fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey stats.addValues(entry); 1052fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey } catch (NumberFormatException e) { 1053fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey Slog.w(TAG, "problem parsing stats row '" + line + "': " + e); 1054fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey } 1055fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey } 1056fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey } catch (IOException e) { 1057fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey Slog.w(TAG, "problem parsing stats: " + e); 1058fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey } finally { 1059fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey IoUtils.closeQuietly(reader); 1060fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey } 1061fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey 1062fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey if (DBG) Slog.d(TAG, "recorded active stats from " + activeIfaces); 1063fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey 1064fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey // splice in stats from any disabled ifaces 1065fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey if (mBandwidthControlEnabled) { 1066fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey final HashSet<String> xtIfaces = Sets.newHashSet(fileListWithoutNull(mStatsXtIface)); 1067fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey xtIfaces.removeAll(activeIfaces); 1068fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey 1069fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey for (String iface : xtIfaces) { 1070fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey final File ifacePath = new File(mStatsXtIface, iface); 1071fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey 1072fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey entry.iface = iface; 1073fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey entry.uid = UID_ALL; 1074fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey entry.tag = TAG_NONE; 1075fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey entry.rxBytes = readSingleLongFromFile(new File(ifacePath, "rx_bytes")); 1076fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey entry.rxPackets = readSingleLongFromFile(new File(ifacePath, "rx_packets")); 1077fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey entry.txBytes = readSingleLongFromFile(new File(ifacePath, "tx_bytes")); 1078fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey entry.txPackets = readSingleLongFromFile(new File(ifacePath, "tx_packets")); 10799a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey 1080fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey stats.addValues(entry); 1081fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey } 1082fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey 1083fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey if (DBG) Slog.d(TAG, "recorded stale stats from " + xtIfaces); 10849a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey } 10859a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey 10864a97122ebf4d92a3f94402041729d77905e6c0c0Jeff Sharkey return stats; 108791cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat } 108891cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat 1089eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey @Override 10909a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey public NetworkStats getNetworkStatsDetail() { 10919a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey mContext.enforceCallingOrSelfPermission( 10929a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService"); 10939a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey 1094350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey if (mBandwidthControlEnabled) { 10951b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey return getNetworkStatsDetailNetfilter(UID_ALL); 10961b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey } else { 10971b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey return getNetworkStatsDetailUidstat(UID_ALL); 10989a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey } 109991cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat } 110091cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat 1101eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey @Override 110241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey public void setInterfaceQuota(String iface, long quotaBytes) { 1103b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG); 1104b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey 1105350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey // silently discard when control disabled 1106350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey // TODO: eventually migrate to be always enabled 1107350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey if (!mBandwidthControlEnabled) return; 1108350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey 110941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey synchronized (mQuotaLock) { 111041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey if (mActiveQuotaIfaces.contains(iface)) { 111141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey throw new IllegalStateException("iface " + iface + " already has quota"); 1112b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey } 1113b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey 1114b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey final StringBuilder command = new StringBuilder(); 111541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey command.append("bandwidth setiquota ").append(iface).append(" ").append(quotaBytes); 1116b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey 1117b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey try { 111841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey // TODO: support quota shared across interfaces 1119b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey mConnector.doCommand(command.toString()); 112041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey mActiveQuotaIfaces.add(iface); 1121b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey } catch (NativeDaemonConnectorException e) { 1122b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey throw new IllegalStateException("Error communicating to native daemon", e); 1123b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey } 112450fd36d7c38c40b087c8f3e3172478abe0c051d9Ashish Sharma } 112550fd36d7c38c40b087c8f3e3172478abe0c051d9Ashish Sharma } 112650fd36d7c38c40b087c8f3e3172478abe0c051d9Ashish Sharma 112750fd36d7c38c40b087c8f3e3172478abe0c051d9Ashish Sharma @Override 1128b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey public void removeInterfaceQuota(String iface) { 1129b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG); 1130b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey 1131350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey // silently discard when control disabled 1132350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey // TODO: eventually migrate to be always enabled 1133350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey if (!mBandwidthControlEnabled) return; 1134350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey 113541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey synchronized (mQuotaLock) { 113641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey if (!mActiveQuotaIfaces.contains(iface)) { 1137b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey // TODO: eventually consider throwing 1138b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey return; 1139b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey } 1140b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey 1141b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey final StringBuilder command = new StringBuilder(); 1142b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey command.append("bandwidth removeiquota ").append(iface); 1143b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey 1144b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey try { 114541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey // TODO: support quota shared across interfaces 1146b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey mConnector.doCommand(command.toString()); 114741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey mActiveQuotaIfaces.remove(iface); 114841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey mActiveAlertIfaces.remove(iface); 1149b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey } catch (NativeDaemonConnectorException e) { 1150b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey throw new IllegalStateException("Error communicating to native daemon", e); 1151b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey } 1152b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey } 1153b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey } 1154b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey 1155b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey @Override 115641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey public void setInterfaceAlert(String iface, long alertBytes) { 115741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG); 115841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey 115941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey // silently discard when control disabled 116041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey // TODO: eventually migrate to be always enabled 116141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey if (!mBandwidthControlEnabled) return; 116241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey 116341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey // quick sanity check 116441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey if (!mActiveQuotaIfaces.contains(iface)) { 116541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey throw new IllegalStateException("setting alert requires existing quota on iface"); 116641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey } 116741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey 116841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey synchronized (mQuotaLock) { 116941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey if (mActiveAlertIfaces.contains(iface)) { 117041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey throw new IllegalStateException("iface " + iface + " already has alert"); 117141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey } 117241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey 117341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey final StringBuilder command = new StringBuilder(); 117441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey command.append("bandwidth setinterfacealert ").append(iface).append(" ").append( 117541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey alertBytes); 117641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey 117741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey try { 117841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey // TODO: support alert shared across interfaces 117941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey mConnector.doCommand(command.toString()); 118041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey mActiveAlertIfaces.add(iface); 118141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey } catch (NativeDaemonConnectorException e) { 118241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey throw new IllegalStateException("Error communicating to native daemon", e); 118341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey } 118441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey } 118541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey } 118641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey 118741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey @Override 118841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey public void removeInterfaceAlert(String iface) { 118941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG); 119041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey 119141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey // silently discard when control disabled 119241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey // TODO: eventually migrate to be always enabled 119341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey if (!mBandwidthControlEnabled) return; 119441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey 119541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey synchronized (mQuotaLock) { 119641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey if (!mActiveAlertIfaces.contains(iface)) { 119741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey // TODO: eventually consider throwing 119841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey return; 119941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey } 120041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey 120141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey final StringBuilder command = new StringBuilder(); 120241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey command.append("bandwidth removeinterfacealert ").append(iface); 120341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey 120441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey try { 120541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey // TODO: support alert shared across interfaces 120641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey mConnector.doCommand(command.toString()); 120741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey mActiveAlertIfaces.remove(iface); 120841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey } catch (NativeDaemonConnectorException e) { 120941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey throw new IllegalStateException("Error communicating to native daemon", e); 121041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey } 121141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey } 121241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey } 121341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey 121441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey @Override 121541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey public void setGlobalAlert(long alertBytes) { 121641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG); 121741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey 121841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey // silently discard when control disabled 121941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey // TODO: eventually migrate to be always enabled 122041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey if (!mBandwidthControlEnabled) return; 122141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey 122241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey final StringBuilder command = new StringBuilder(); 122341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey command.append("bandwidth setglobalalert ").append(alertBytes); 122441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey 122541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey try { 122641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey mConnector.doCommand(command.toString()); 122741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey } catch (NativeDaemonConnectorException e) { 122841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey throw new IllegalStateException("Error communicating to native daemon", e); 122941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey } 123041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey } 123141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey 123241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey @Override 1233b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey public void setUidNetworkRules(int uid, boolean rejectOnQuotaInterfaces) { 1234b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG); 1235b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey 1236350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey // silently discard when control disabled 1237350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey // TODO: eventually migrate to be always enabled 1238350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey if (!mBandwidthControlEnabled) return; 1239350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey 1240b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey synchronized (mUidRejectOnQuota) { 1241b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey final boolean oldRejectOnQuota = mUidRejectOnQuota.get(uid, false); 1242b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey if (oldRejectOnQuota == rejectOnQuotaInterfaces) { 1243b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey // TODO: eventually consider throwing 1244b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey return; 1245b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey } 1246b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey 1247b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey final StringBuilder command = new StringBuilder(); 1248b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey command.append("bandwidth"); 1249b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey if (rejectOnQuotaInterfaces) { 1250b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey command.append(" addnaughtyapps"); 1251b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey } else { 1252b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey command.append(" removenaughtyapps"); 1253b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey } 1254b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey command.append(" ").append(uid); 1255b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey 1256b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey try { 1257b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey mConnector.doCommand(command.toString()); 1258b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey if (rejectOnQuotaInterfaces) { 1259b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey mUidRejectOnQuota.put(uid, true); 1260b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey } else { 1261b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey mUidRejectOnQuota.delete(uid); 1262b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey } 1263b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey } catch (NativeDaemonConnectorException e) { 1264b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey throw new IllegalStateException("Error communicating to native daemon", e); 1265b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey } 126650fd36d7c38c40b087c8f3e3172478abe0c051d9Ashish Sharma } 126750fd36d7c38c40b087c8f3e3172478abe0c051d9Ashish Sharma } 126850fd36d7c38c40b087c8f3e3172478abe0c051d9Ashish Sharma 126963d27a9233fed934340231f438493746084a681dJeff Sharkey @Override 127063d27a9233fed934340231f438493746084a681dJeff Sharkey public boolean isBandwidthControlEnabled() { 127163d27a9233fed934340231f438493746084a681dJeff Sharkey mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG); 127263d27a9233fed934340231f438493746084a681dJeff Sharkey return mBandwidthControlEnabled; 127363d27a9233fed934340231f438493746084a681dJeff Sharkey } 127463d27a9233fed934340231f438493746084a681dJeff Sharkey 127563d27a9233fed934340231f438493746084a681dJeff Sharkey @Override 1276eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey public NetworkStats getNetworkStatsUidDetail(int uid) { 1277eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey if (Binder.getCallingUid() != uid) { 1278eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey mContext.enforceCallingOrSelfPermission( 1279eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService"); 1280eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey } 1281eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey 1282350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey if (mBandwidthControlEnabled) { 12831b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey return getNetworkStatsDetailNetfilter(uid); 12841b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey } else { 12851b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey return getNetworkStatsDetailUidstat(uid); 12861b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey } 12871b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey } 12881b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey 12891b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey /** 12901b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey * Build {@link NetworkStats} with detailed UID statistics. 12911b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey */ 12921b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey private NetworkStats getNetworkStatsDetailNetfilter(int limitUid) { 12931b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 24); 1294fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey final NetworkStats.Entry entry = new NetworkStats.Entry(); 1295fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey 1296a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey // TODO: remove knownLines check once 5087722 verified 1297a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey final HashSet<String> knownLines = Sets.newHashSet(); 1298a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey 12994414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey final ArrayList<String> keys = Lists.newArrayList(); 13004414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey final ArrayList<String> values = Lists.newArrayList(); 13014414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey final HashMap<String, String> parsed = Maps.newHashMap(); 13021b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey 13031b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey BufferedReader reader = null; 13041b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey try { 1305fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey reader = new BufferedReader(new FileReader(mStatsXtUid)); 13061b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey 13074414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey // parse first line as header 13081b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey String line = reader.readLine(); 13094414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey splitLine(line, keys); 13101b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey 13114414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey // parse remaining lines 13124414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey while ((line = reader.readLine()) != null) { 13134414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey splitLine(line, values); 13144414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey parseLine(keys, values, parsed); 13151b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey 1316a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey if (!knownLines.add(line)) { 1317a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey throw new IllegalStateException("encountered duplicate proc entry"); 1318a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey } 1319a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey 13201b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey try { 1321fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey entry.iface = parsed.get(KEY_IFACE); 1322a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey entry.tag = kernelToTag(parsed.get(KEY_TAG_HEX)); 1323a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey entry.uid = getParsedInt(parsed, KEY_UID); 1324a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey entry.rxBytes = getParsedLong(parsed, KEY_RX_BYTES); 1325a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey entry.rxPackets = getParsedLong(parsed, KEY_RX_PACKETS); 1326a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey entry.txBytes = getParsedLong(parsed, KEY_TX_BYTES); 1327a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey entry.txPackets = getParsedLong(parsed, KEY_TX_PACKETS); 1328d03fd3f004e3ba8aaa1692ee0e92e8ae171d2a04Jeff Sharkey 1329fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey if (limitUid == UID_ALL || limitUid == entry.uid) { 1330fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey stats.addValues(entry); 13311b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey } 13321b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey } catch (NumberFormatException e) { 13334414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey Slog.w(TAG, "problem parsing stats row '" + line + "': " + e); 13341b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey } 13351b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey } 13361b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey } catch (IOException e) { 13371b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey Slog.w(TAG, "problem parsing stats: " + e); 13381b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey } finally { 13391b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey IoUtils.closeQuietly(reader); 13401b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey } 13411b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey 13424a97122ebf4d92a3f94402041729d77905e6c0c0Jeff Sharkey return stats; 1343eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey } 1344eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey 1345a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey private static int getParsedInt(HashMap<String, String> parsed, String key) { 1346a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey final String value = parsed.get(key); 1347a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey return value != null ? Integer.parseInt(value) : 0; 1348a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey } 1349a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey 1350a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey private static long getParsedLong(HashMap<String, String> parsed, String key) { 1351a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey final String value = parsed.get(key); 1352a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey return value != null ? Long.parseLong(value) : 0; 1353a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey } 1354a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey 13551b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey /** 13561b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey * Build {@link NetworkStats} with detailed UID statistics. 13571b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey * 13581b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey * @deprecated since this uses older "uid_stat" data, and doesn't provide 13591b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey * tag-level granularity or additional variables. 13601b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey */ 13611b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey @Deprecated 13621b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey private NetworkStats getNetworkStatsDetailUidstat(int limitUid) { 13631b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey final String[] knownUids; 13641b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey if (limitUid == UID_ALL) { 1365fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey knownUids = fileListWithoutNull(mStatsUid); 13661b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey } else { 13671b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey knownUids = new String[] { String.valueOf(limitUid) }; 13681b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey } 13691b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey 13701b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey final NetworkStats stats = new NetworkStats( 13711b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey SystemClock.elapsedRealtime(), knownUids.length); 1372fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey final NetworkStats.Entry entry = new NetworkStats.Entry(); 13731b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey for (String uid : knownUids) { 13741b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey final int uidInt = Integer.parseInt(uid); 1375fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey final File uidPath = new File(mStatsUid, uid); 1376fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey 1377fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey entry.iface = IFACE_ALL; 1378fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey entry.uid = uidInt; 1379fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey entry.tag = TAG_NONE; 1380fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey entry.rxBytes = readSingleLongFromFile(new File(uidPath, "tcp_rcv")); 1381fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey entry.rxPackets = readSingleLongFromFile(new File(uidPath, "tcp_rcv_pkt")); 1382fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey entry.txBytes = readSingleLongFromFile(new File(uidPath, "tcp_snd")); 1383fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey entry.txPackets = readSingleLongFromFile(new File(uidPath, "tcp_snd_pkt")); 1384fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey 1385fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey stats.addValues(entry); 13861b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey } 13871b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey 13881b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey return stats; 1389eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey } 1390eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey 1391f0db6e1853e929ae3b65501c31ee57c4dfbc767cSan Mehat public void setInterfaceThrottle(String iface, int rxKbps, int txKbps) { 139291cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat mContext.enforceCallingOrSelfPermission( 139391cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService"); 1394a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root try { 1395a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root mConnector.doCommand(String.format( 1396a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root "interface setthrottle %s %d %d", iface, rxKbps, txKbps)); 1397a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } catch (NativeDaemonConnectorException e) { 1398a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root Slog.e(TAG, "Error communicating with native daemon to set throttle", e); 1399a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } 140091cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat } 140191cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat 140291cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat private int getInterfaceThrottle(String iface, boolean rx) { 140391cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat mContext.enforceCallingOrSelfPermission( 140491cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService"); 140591cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat try { 1406a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root String rsp; 1407a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root try { 1408a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root rsp = mConnector.doCommand( 1409a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root String.format("interface getthrottle %s %s", iface, 1410a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root (rx ? "rx" : "tx"))).get(0); 1411a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } catch (NativeDaemonConnectorException e) { 1412a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root Slog.e(TAG, "Error communicating with native daemon to getthrottle", e); 1413a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root return -1; 1414a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } 1415a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root 1416a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root String[] tok = rsp.split(" "); 1417a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root if (tok.length < 2) { 1418a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root Slog.e(TAG, "Malformed response to getthrottle command"); 1419a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root return -1; 1420a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root } 1421a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root 142291cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat int code; 142391cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat try { 142491cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat code = Integer.parseInt(tok[0]); 142591cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat } catch (NumberFormatException nfe) { 142691cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat Slog.e(TAG, String.format("Error parsing code %s", tok[0])); 142791cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat return -1; 142891cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat } 142991cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat if ((rx && code != NetdResponseCode.InterfaceRxThrottleResult) || ( 143091cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat !rx && code != NetdResponseCode.InterfaceTxThrottleResult)) { 143191cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat Slog.e(TAG, String.format("Unexpected response code %d", code)); 143291cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat return -1; 143391cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat } 143491cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat return Integer.parseInt(tok[1]); 143591cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat } catch (Exception e) { 143691cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat Slog.e(TAG, String.format( 143791cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat "Failed to read interface %s throttle value", (rx ? "rx" : "tx")), e); 143891cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat } 143991cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat return -1; 144091cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat } 144191cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat 144291cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat public int getInterfaceRxThrottle(String iface) { 144391cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat return getInterfaceThrottle(iface, true); 144491cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat } 144591cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat 144691cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat public int getInterfaceTxThrottle(String iface) { 144791cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat return getInterfaceThrottle(iface, false); 144891cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat } 14499a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey 14509a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey /** 14514414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey * Split given line into {@link ArrayList}. 14524414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey */ 14534414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey private static void splitLine(String line, ArrayList<String> outSplit) { 14544414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey outSplit.clear(); 14554414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey 1456fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey final StringTokenizer t = new StringTokenizer(line, " \t\n\r\f:"); 14574414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey while (t.hasMoreTokens()) { 14584414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey outSplit.add(t.nextToken()); 14594414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey } 14604414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey } 14614414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey 14624414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey /** 14634414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey * Zip the two given {@link ArrayList} as key and value pairs into 14644414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey * {@link HashMap}. 14654414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey */ 14664414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey private static void parseLine( 14674414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey ArrayList<String> keys, ArrayList<String> values, HashMap<String, String> outParsed) { 14684414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey outParsed.clear(); 14694414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey 14704414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey final int size = Math.min(keys.size(), values.size()); 14714414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey for (int i = 0; i < size; i++) { 14724414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey outParsed.put(keys.get(i), values.get(i)); 14734414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey } 14744414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey } 14754414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey 14764414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey /** 1477eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey * Utility method to read a single plain-text {@link Long} from the given 14789a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey * {@link File}, usually from a {@code /proc/} filesystem. 14799a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey */ 1480eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey private static long readSingleLongFromFile(File file) { 14819a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey try { 1482eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey final byte[] buffer = IoUtils.readFileAsByteArray(file.toString()); 1483eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey return Long.parseLong(new String(buffer).trim()); 14849a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey } catch (NumberFormatException e) { 14859a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey return -1; 14869a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey } catch (IOException e) { 14879a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey return -1; 14889a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey } 14899a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey } 1490d5299ff39aa7532c0213978fc0a95e08c3a77debJean-Baptiste Queru 1491fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey /** 1492fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey * Wrapper for {@link File#list()} that returns empty array instead of 1493fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey * {@code null}. 1494fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey */ 1495fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey private static String[] fileListWithoutNull(File file) { 1496fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey final String[] list = file.list(); 1497fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey return list != null ? list : new String[0]; 1498fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey } 1499fd8be3e5e7420f3cca591daeec8a44487f5f65aaJeff Sharkey 15007475c0cea622f126af966c3b5b9741f547e83450Mattias Falk public void setDefaultInterfaceForDns(String iface) throws IllegalStateException { 15017475c0cea622f126af966c3b5b9741f547e83450Mattias Falk mContext.enforceCallingOrSelfPermission( 15027475c0cea622f126af966c3b5b9741f547e83450Mattias Falk android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService"); 15037475c0cea622f126af966c3b5b9741f547e83450Mattias Falk try { 15047475c0cea622f126af966c3b5b9741f547e83450Mattias Falk String cmd = "resolver setdefaultif " + iface; 15057475c0cea622f126af966c3b5b9741f547e83450Mattias Falk 15067475c0cea622f126af966c3b5b9741f547e83450Mattias Falk mConnector.doCommand(cmd); 15077475c0cea622f126af966c3b5b9741f547e83450Mattias Falk } catch (NativeDaemonConnectorException e) { 15087475c0cea622f126af966c3b5b9741f547e83450Mattias Falk throw new IllegalStateException( 15097475c0cea622f126af966c3b5b9741f547e83450Mattias Falk "Error communicating with native daemon to set default interface", e); 15107475c0cea622f126af966c3b5b9741f547e83450Mattias Falk } 15117475c0cea622f126af966c3b5b9741f547e83450Mattias Falk } 15127475c0cea622f126af966c3b5b9741f547e83450Mattias Falk 15137475c0cea622f126af966c3b5b9741f547e83450Mattias Falk public void setDnsServersForInterface(String iface, String[] servers) 15147475c0cea622f126af966c3b5b9741f547e83450Mattias Falk throws IllegalStateException { 15157475c0cea622f126af966c3b5b9741f547e83450Mattias Falk mContext.enforceCallingOrSelfPermission(android.Manifest.permission.CHANGE_NETWORK_STATE, 15167475c0cea622f126af966c3b5b9741f547e83450Mattias Falk "NetworkManagementService"); 15177475c0cea622f126af966c3b5b9741f547e83450Mattias Falk try { 15187475c0cea622f126af966c3b5b9741f547e83450Mattias Falk String cmd = "resolver setifdns " + iface; 15197475c0cea622f126af966c3b5b9741f547e83450Mattias Falk for (String s : servers) { 1520572b7048a6ed6cf6c5f6bc6c9d542dc377d601ffRobert Greenwalt InetAddress a = NetworkUtils.numericToInetAddress(s); 1521572b7048a6ed6cf6c5f6bc6c9d542dc377d601ffRobert Greenwalt if (a.isAnyLocalAddress() == false) { 1522572b7048a6ed6cf6c5f6bc6c9d542dc377d601ffRobert Greenwalt cmd += " " + a.getHostAddress(); 15237475c0cea622f126af966c3b5b9741f547e83450Mattias Falk } 15247475c0cea622f126af966c3b5b9741f547e83450Mattias Falk } 15257475c0cea622f126af966c3b5b9741f547e83450Mattias Falk mConnector.doCommand(cmd); 1526572b7048a6ed6cf6c5f6bc6c9d542dc377d601ffRobert Greenwalt } catch (IllegalArgumentException e) { 1527572b7048a6ed6cf6c5f6bc6c9d542dc377d601ffRobert Greenwalt throw new IllegalStateException("Error setting dnsn for interface", e); 15287475c0cea622f126af966c3b5b9741f547e83450Mattias Falk } catch (NativeDaemonConnectorException e) { 15297475c0cea622f126af966c3b5b9741f547e83450Mattias Falk throw new IllegalStateException( 1530572b7048a6ed6cf6c5f6bc6c9d542dc377d601ffRobert Greenwalt "Error communicating with native daemon to set dns for interface", e); 15317475c0cea622f126af966c3b5b9741f547e83450Mattias Falk } 15327475c0cea622f126af966c3b5b9741f547e83450Mattias Falk } 15337475c0cea622f126af966c3b5b9741f547e83450Mattias Falk 15347475c0cea622f126af966c3b5b9741f547e83450Mattias Falk public void flushDefaultDnsCache() throws IllegalStateException { 15357475c0cea622f126af966c3b5b9741f547e83450Mattias Falk mContext.enforceCallingOrSelfPermission( 15367475c0cea622f126af966c3b5b9741f547e83450Mattias Falk android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService"); 15377475c0cea622f126af966c3b5b9741f547e83450Mattias Falk try { 15387475c0cea622f126af966c3b5b9741f547e83450Mattias Falk String cmd = "resolver flushdefaultif"; 15397475c0cea622f126af966c3b5b9741f547e83450Mattias Falk 15407475c0cea622f126af966c3b5b9741f547e83450Mattias Falk mConnector.doCommand(cmd); 15417475c0cea622f126af966c3b5b9741f547e83450Mattias Falk } catch (NativeDaemonConnectorException e) { 15427475c0cea622f126af966c3b5b9741f547e83450Mattias Falk throw new IllegalStateException( 15437475c0cea622f126af966c3b5b9741f547e83450Mattias Falk "Error communicating with native deamon to flush default interface", e); 15447475c0cea622f126af966c3b5b9741f547e83450Mattias Falk } 15457475c0cea622f126af966c3b5b9741f547e83450Mattias Falk } 15467475c0cea622f126af966c3b5b9741f547e83450Mattias Falk 15477475c0cea622f126af966c3b5b9741f547e83450Mattias Falk public void flushInterfaceDnsCache(String iface) throws IllegalStateException { 15487475c0cea622f126af966c3b5b9741f547e83450Mattias Falk mContext.enforceCallingOrSelfPermission( 15497475c0cea622f126af966c3b5b9741f547e83450Mattias Falk android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService"); 15507475c0cea622f126af966c3b5b9741f547e83450Mattias Falk try { 15517475c0cea622f126af966c3b5b9741f547e83450Mattias Falk String cmd = "resolver flushif " + iface; 15527475c0cea622f126af966c3b5b9741f547e83450Mattias Falk 15537475c0cea622f126af966c3b5b9741f547e83450Mattias Falk mConnector.doCommand(cmd); 15547475c0cea622f126af966c3b5b9741f547e83450Mattias Falk } catch (NativeDaemonConnectorException e) { 15557475c0cea622f126af966c3b5b9741f547e83450Mattias Falk throw new IllegalStateException( 1556572b7048a6ed6cf6c5f6bc6c9d542dc377d601ffRobert Greenwalt "Error communicating with native daemon to flush interface " + iface, e); 15577475c0cea622f126af966c3b5b9741f547e83450Mattias Falk } 15587475c0cea622f126af966c3b5b9741f547e83450Mattias Falk } 1559873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat} 1560