NetworkManagementService.java revision 00a0fd650b7a31dffb88c229242bb04fa0b487a4
165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn/* 265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * Copyright (C) 2007 The Android Open Source Project 365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * 465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * Licensed under the Apache License, Version 2.0 (the "License"); 565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * you may not use this file except in compliance with the License. 665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * You may obtain a copy of the License at 765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * 865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * http://www.apache.org/licenses/LICENSE-2.0 965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * 1065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * Unless required by applicable law or agreed to in writing, software 1165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * distributed under the License is distributed on an "AS IS" BASIS, 1265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * See the License for the specific language governing permissions and 1465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * limitations under the License. 1565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn */ 1665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 1765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennpackage com.android.server; 1865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 1965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport static android.Manifest.permission.CHANGE_NETWORK_STATE; 2065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport static android.Manifest.permission.CONNECTIVITY_INTERNAL; 2165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport static android.Manifest.permission.DUMP; 2265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport static android.Manifest.permission.SHUTDOWN; 2365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport static android.net.NetworkStats.SET_DEFAULT; 2465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport static android.net.NetworkStats.TAG_ALL; 2565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport static android.net.NetworkStats.TAG_NONE; 2665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport static android.net.NetworkStats.UID_ALL; 2765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport static android.net.TrafficStats.UID_TETHERING; 2865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport static com.android.server.NetworkManagementService.NetdResponseCode.ClatdStatusResult; 2965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport static com.android.server.NetworkManagementService.NetdResponseCode.GetMarkResult; 3065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport static com.android.server.NetworkManagementService.NetdResponseCode.InterfaceGetCfgResult; 3165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport static com.android.server.NetworkManagementService.NetdResponseCode.InterfaceListResult; 3265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport static com.android.server.NetworkManagementService.NetdResponseCode.IpFwdStatusResult; 3365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport static com.android.server.NetworkManagementService.NetdResponseCode.TetherDnsFwdTgtListResult; 3465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport static com.android.server.NetworkManagementService.NetdResponseCode.TetherInterfaceListResult; 3565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport static com.android.server.NetworkManagementService.NetdResponseCode.TetherStatusResult; 3665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport static com.android.server.NetworkManagementService.NetdResponseCode.TetheringStatsListResult; 3765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport static com.android.server.NetworkManagementService.NetdResponseCode.TtyListResult; 3865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport static com.android.server.NetworkManagementSocketTagger.PROP_QTAGUID_ENABLED; 3965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 4065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport android.content.Context; 4165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport android.net.ConnectivityManager; 4265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport android.net.INetworkManagementEventObserver; 4365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport android.net.InterfaceConfiguration; 4465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport android.net.LinkAddress; 4565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport android.net.NetworkStats; 4665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport android.net.NetworkUtils; 4765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport android.net.RouteInfo; 4865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport android.net.wifi.WifiConfiguration; 4965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport android.net.wifi.WifiConfiguration.KeyMgmt; 5065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport android.os.BatteryStats; 5165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport android.os.Binder; 5265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport android.os.Handler; 5365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport android.os.INetworkActivityListener; 5465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport android.os.INetworkManagementService; 5565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport android.os.PowerManager; 5665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport android.os.Process; 5765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport android.os.RemoteCallbackList; 5865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport android.os.RemoteException; 5965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport android.os.ServiceManager; 6065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport android.os.SystemClock; 6165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport android.os.SystemProperties; 6265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport android.telephony.DataConnectionRealTimeInfo; 6365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport android.telephony.PhoneStateListener; 6465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport android.util.Log; 6565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport android.util.Slog; 6665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport android.util.SparseBooleanArray; 6765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 6865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport com.android.internal.app.IBatteryStats; 6965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport com.android.internal.net.NetworkStatsFactory; 7065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport com.android.internal.util.Preconditions; 7165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport com.android.server.NativeDaemonConnector.Command; 7265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport com.android.server.NativeDaemonConnector.SensitiveArg; 7365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport com.android.server.net.LockdownVpnTracker; 7465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport com.google.android.collect.Maps; 7565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 7665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport java.io.BufferedReader; 7765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport java.io.DataInputStream; 7865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport java.io.File; 7965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport java.io.FileDescriptor; 8065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport java.io.FileInputStream; 8165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport java.io.IOException; 8265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport java.io.InputStreamReader; 8365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport java.io.PrintWriter; 8465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport java.net.Inet4Address; 8565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport java.net.InetAddress; 8665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport java.net.InterfaceAddress; 8765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport java.net.NetworkInterface; 8865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport java.net.SocketException; 8965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport java.util.ArrayList; 9065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport java.util.HashMap; 9165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport java.util.List; 9265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport java.util.Map; 9365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport java.util.NoSuchElementException; 9465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport java.util.StringTokenizer; 9565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport java.util.concurrent.CountDownLatch; 9665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 9765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn/** 9865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * @hide 9965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn */ 10065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennpublic class NetworkManagementService extends INetworkManagementService.Stub 10165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn implements Watchdog.Monitor { 10265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private static final String TAG = "NetworkManagementService"; 10365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private static final boolean DBG = false; 10465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private static final String NETD_TAG = "NetdConnector"; 10565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private static final String NETD_SOCKET_NAME = "netd"; 10665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 10765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private static final String ADD = "add"; 10865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private static final String REMOVE = "remove"; 10965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 11065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private static final String ALLOW = "allow"; 11165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private static final String DENY = "deny"; 11265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 11365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private static final String DEFAULT = "default"; 11465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private static final String SECONDARY = "secondary"; 11565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 11665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn /** 11765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * Name representing {@link #setGlobalAlert(long)} limit when delivered to 11865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * {@link INetworkManagementEventObserver#limitReached(String, String)}. 11965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn */ 12065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn public static final String LIMIT_GLOBAL_ALERT = "globalAlert"; 12165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 12265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn class NetdResponseCode { 12365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn /* Keep in sync with system/netd/ResponseCode.h */ 12465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn public static final int InterfaceListResult = 110; 12565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn public static final int TetherInterfaceListResult = 111; 12665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn public static final int TetherDnsFwdTgtListResult = 112; 12765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn public static final int TtyListResult = 113; 12865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn public static final int TetheringStatsListResult = 114; 12965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 13065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn public static final int TetherStatusResult = 210; 13165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn public static final int IpFwdStatusResult = 211; 13265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn public static final int InterfaceGetCfgResult = 213; 13365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn public static final int SoftapStatusResult = 214; 13465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn public static final int InterfaceRxCounterResult = 216; 13565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn public static final int InterfaceTxCounterResult = 217; 13665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn public static final int QuotaCounterResult = 220; 13765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn public static final int TetheringStatsResult = 221; 13865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn public static final int DnsProxyQueryResult = 222; 13965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn public static final int ClatdStatusResult = 223; 14065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn public static final int GetMarkResult = 225; 14165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 14265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn public static final int InterfaceChange = 600; 14365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn public static final int BandwidthControl = 601; 14465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn public static final int InterfaceClassActivity = 613; 14565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn public static final int InterfaceAddressChange = 614; 14665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn public static final int InterfaceDnsServerInfo = 615; 14765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 14865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 14965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn static final int DAEMON_MSG_MOBILE_CONN_REAL_TIME_INFO = 1; 15065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 15165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn /** 15265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * Binder context for this service 15365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn */ 15465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private final Context mContext; 15565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 15665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn /** 15765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * connector object for communicating with netd 15865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn */ 15965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private final NativeDaemonConnector mConnector; 16065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 16165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private final Handler mFgHandler; 16265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private final Handler mDaemonHandler; 16365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private final PhoneStateListener mPhoneStateListener; 16465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 16565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private IBatteryStats mBatteryStats; 16665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 16765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private final Thread mThread; 16865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private CountDownLatch mConnectedSignal = new CountDownLatch(1); 16965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 17065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private final RemoteCallbackList<INetworkManagementEventObserver> mObservers = 17165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn new RemoteCallbackList<INetworkManagementEventObserver>(); 17265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 17365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private final NetworkStatsFactory mStatsFactory = new NetworkStatsFactory(); 17465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 17565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private Object mQuotaLock = new Object(); 17665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn /** Set of interfaces with active quotas. */ 17765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private HashMap<String, Long> mActiveQuotas = Maps.newHashMap(); 17865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn /** Set of interfaces with active alerts. */ 17965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private HashMap<String, Long> mActiveAlerts = Maps.newHashMap(); 18065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn /** Set of UIDs with active reject rules. */ 18165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private SparseBooleanArray mUidRejectOnQuota = new SparseBooleanArray(); 18265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 18365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private Object mIdleTimerLock = new Object(); 18465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn /** Set of interfaces with active idle timers. */ 18565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private static class IdleTimerParams { 18665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn public final int timeout; 18765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn public final int type; 18865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn public int networkCount; 18965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 19065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn IdleTimerParams(int timeout, int type) { 19165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn this.timeout = timeout; 19265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn this.type = type; 19365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn this.networkCount = 1; 19465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 19565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 19665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private HashMap<String, IdleTimerParams> mActiveIdleTimers = Maps.newHashMap(); 19765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 19865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private volatile boolean mBandwidthControlEnabled; 19965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private volatile boolean mFirewallEnabled; 20065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 20165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private boolean mMobileActivityFromRadio = false; 20265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private int mLastPowerStateFromRadio = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW; 20365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 20465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private final RemoteCallbackList<INetworkActivityListener> mNetworkActivityListeners = 20565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn new RemoteCallbackList<INetworkActivityListener>(); 20665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private boolean mNetworkActive; 20765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 20865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn /** 20965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * Constructs a new NetworkManagementService instance 21065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * 21165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * @param context Binder context for this service 21265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn */ 21365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private NetworkManagementService(Context context, String socket) { 21465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn mContext = context; 21565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 21665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // make sure this is on the same looper as our NativeDaemonConnector for sync purposes 21765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn mFgHandler = new Handler(FgThread.get().getLooper()); 218 219 if ("simulator".equals(SystemProperties.get("ro.product.device"))) { 220 mConnector = null; 221 mThread = null; 222 mDaemonHandler = null; 223 mPhoneStateListener = null; 224 return; 225 } 226 227 // Don't need this wake lock, since we now have a time stamp for when 228 // the network actually went inactive. (It might be nice to still do this, 229 // but I don't want to do it through the power manager because that pollutes the 230 // battery stats history with pointless noise.) 231 //PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE); 232 PowerManager.WakeLock wl = null; //pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, NETD_TAG); 233 234 mConnector = new NativeDaemonConnector( 235 new NetdCallbackReceiver(), socket, 10, NETD_TAG, 160, wl, 236 FgThread.get().getLooper()); 237 mThread = new Thread(mConnector, NETD_TAG); 238 239 mDaemonHandler = new Handler(FgThread.get().getLooper()); 240 mPhoneStateListener = new PhoneStateListener(mDaemonHandler.getLooper()) { 241 public void onDataConnectionRealTimeInfoChanged( 242 DataConnectionRealTimeInfo dcRtInfo) { 243 notifyInterfaceClassActivity(ConnectivityManager.TYPE_MOBILE, 244 dcRtInfo.getDcPowerState(), dcRtInfo.getTime(), true); 245 } 246 }; 247 248 // Add ourself to the Watchdog monitors. 249 Watchdog.getInstance().addMonitor(this); 250 } 251 252 static NetworkManagementService create(Context context, 253 String socket) throws InterruptedException { 254 final NetworkManagementService service = new NetworkManagementService(context, socket); 255 final CountDownLatch connectedSignal = service.mConnectedSignal; 256 if (DBG) Slog.d(TAG, "Creating NetworkManagementService"); 257 service.mThread.start(); 258 if (DBG) Slog.d(TAG, "Awaiting socket connection"); 259 connectedSignal.await(); 260 if (DBG) Slog.d(TAG, "Connected"); 261 return service; 262 } 263 264 public static NetworkManagementService create(Context context) throws InterruptedException { 265 return create(context, NETD_SOCKET_NAME); 266 } 267 268 public void systemReady() { 269 prepareNativeDaemon(); 270 if (DBG) Slog.d(TAG, "Prepared"); 271 } 272 273 private IBatteryStats getBatteryStats() { 274 synchronized (this) { 275 if (mBatteryStats != null) { 276 return mBatteryStats; 277 } 278 mBatteryStats = IBatteryStats.Stub.asInterface(ServiceManager.getService( 279 BatteryStats.SERVICE_NAME)); 280 return mBatteryStats; 281 } 282 } 283 284 @Override 285 public void registerObserver(INetworkManagementEventObserver observer) { 286 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 287 mObservers.register(observer); 288 } 289 290 @Override 291 public void unregisterObserver(INetworkManagementEventObserver observer) { 292 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 293 mObservers.unregister(observer); 294 } 295 296 /** 297 * Notify our observers of an interface status change 298 */ 299 private void notifyInterfaceStatusChanged(String iface, boolean up) { 300 final int length = mObservers.beginBroadcast(); 301 try { 302 for (int i = 0; i < length; i++) { 303 try { 304 mObservers.getBroadcastItem(i).interfaceStatusChanged(iface, up); 305 } catch (RemoteException e) { 306 } catch (RuntimeException e) { 307 } 308 } 309 } finally { 310 mObservers.finishBroadcast(); 311 } 312 } 313 314 /** 315 * Notify our observers of an interface link state change 316 * (typically, an Ethernet cable has been plugged-in or unplugged). 317 */ 318 private void notifyInterfaceLinkStateChanged(String iface, boolean up) { 319 final int length = mObservers.beginBroadcast(); 320 try { 321 for (int i = 0; i < length; i++) { 322 try { 323 mObservers.getBroadcastItem(i).interfaceLinkStateChanged(iface, up); 324 } catch (RemoteException e) { 325 } catch (RuntimeException e) { 326 } 327 } 328 } finally { 329 mObservers.finishBroadcast(); 330 } 331 } 332 333 /** 334 * Notify our observers of an interface addition. 335 */ 336 private void notifyInterfaceAdded(String iface) { 337 final int length = mObservers.beginBroadcast(); 338 try { 339 for (int i = 0; i < length; i++) { 340 try { 341 mObservers.getBroadcastItem(i).interfaceAdded(iface); 342 } catch (RemoteException e) { 343 } catch (RuntimeException e) { 344 } 345 } 346 } finally { 347 mObservers.finishBroadcast(); 348 } 349 } 350 351 /** 352 * Notify our observers of an interface removal. 353 */ 354 private void notifyInterfaceRemoved(String iface) { 355 // netd already clears out quota and alerts for removed ifaces; update 356 // our sanity-checking state. 357 mActiveAlerts.remove(iface); 358 mActiveQuotas.remove(iface); 359 360 final int length = mObservers.beginBroadcast(); 361 try { 362 for (int i = 0; i < length; i++) { 363 try { 364 mObservers.getBroadcastItem(i).interfaceRemoved(iface); 365 } catch (RemoteException e) { 366 } catch (RuntimeException e) { 367 } 368 } 369 } finally { 370 mObservers.finishBroadcast(); 371 } 372 } 373 374 /** 375 * Notify our observers of a limit reached. 376 */ 377 private void notifyLimitReached(String limitName, String iface) { 378 final int length = mObservers.beginBroadcast(); 379 try { 380 for (int i = 0; i < length; i++) { 381 try { 382 mObservers.getBroadcastItem(i).limitReached(limitName, iface); 383 } catch (RemoteException e) { 384 } catch (RuntimeException e) { 385 } 386 } 387 } finally { 388 mObservers.finishBroadcast(); 389 } 390 } 391 392 /** 393 * Notify our observers of a change in the data activity state of the interface 394 */ 395 private void notifyInterfaceClassActivity(int type, int powerState, long tsNanos, 396 boolean fromRadio) { 397 final boolean isMobile = ConnectivityManager.isNetworkTypeMobile(type); 398 if (isMobile) { 399 if (!fromRadio) { 400 if (mMobileActivityFromRadio) { 401 // If this call is not coming from a report from the radio itself, but we 402 // have previously received reports from the radio, then we will take the 403 // power state to just be whatever the radio last reported. 404 powerState = mLastPowerStateFromRadio; 405 } 406 } else { 407 mMobileActivityFromRadio = true; 408 } 409 if (mLastPowerStateFromRadio != powerState) { 410 mLastPowerStateFromRadio = powerState; 411 try { 412 getBatteryStats().noteMobileRadioPowerState(powerState, tsNanos); 413 } catch (RemoteException e) { 414 } 415 } 416 } 417 418 boolean isActive = powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_MEDIUM 419 || powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH; 420 421 if (!isMobile || fromRadio || !mMobileActivityFromRadio) { 422 // Report the change in data activity. We don't do this if this is a change 423 // on the mobile network, that is not coming from the radio itself, and we 424 // have previously seen change reports from the radio. In that case only 425 // the radio is the authority for the current state. 426 final int length = mObservers.beginBroadcast(); 427 try { 428 for (int i = 0; i < length; i++) { 429 try { 430 mObservers.getBroadcastItem(i).interfaceClassDataActivityChanged( 431 Integer.toString(type), isActive, tsNanos); 432 } catch (RemoteException e) { 433 } catch (RuntimeException e) { 434 } 435 } 436 } finally { 437 mObservers.finishBroadcast(); 438 } 439 } 440 441 boolean report = false; 442 synchronized (mIdleTimerLock) { 443 if (mActiveIdleTimers.isEmpty()) { 444 // If there are no idle timers, we are not monitoring activity, so we 445 // are always considered active. 446 isActive = true; 447 } 448 if (mNetworkActive != isActive) { 449 mNetworkActive = isActive; 450 report = isActive; 451 } 452 } 453 if (report) { 454 reportNetworkActive(); 455 } 456 } 457 458 /** 459 * Prepare native daemon once connected, enabling modules and pushing any 460 * existing in-memory rules. 461 */ 462 private void prepareNativeDaemon() { 463 mBandwidthControlEnabled = false; 464 465 // only enable bandwidth control when support exists 466 final boolean hasKernelSupport = new File("/proc/net/xt_qtaguid/ctrl").exists(); 467 if (hasKernelSupport) { 468 Slog.d(TAG, "enabling bandwidth control"); 469 try { 470 mConnector.execute("bandwidth", "enable"); 471 mBandwidthControlEnabled = true; 472 } catch (NativeDaemonConnectorException e) { 473 Log.wtf(TAG, "problem enabling bandwidth controls", e); 474 } 475 } else { 476 Slog.d(TAG, "not enabling bandwidth control"); 477 } 478 479 SystemProperties.set(PROP_QTAGUID_ENABLED, mBandwidthControlEnabled ? "1" : "0"); 480 481 if (mBandwidthControlEnabled) { 482 try { 483 getBatteryStats().noteNetworkStatsEnabled(); 484 } catch (RemoteException e) { 485 } 486 } 487 488 // push any existing quota or UID rules 489 synchronized (mQuotaLock) { 490 int size = mActiveQuotas.size(); 491 if (size > 0) { 492 Slog.d(TAG, "pushing " + size + " active quota rules"); 493 final HashMap<String, Long> activeQuotas = mActiveQuotas; 494 mActiveQuotas = Maps.newHashMap(); 495 for (Map.Entry<String, Long> entry : activeQuotas.entrySet()) { 496 setInterfaceQuota(entry.getKey(), entry.getValue()); 497 } 498 } 499 500 size = mActiveAlerts.size(); 501 if (size > 0) { 502 Slog.d(TAG, "pushing " + size + " active alert rules"); 503 final HashMap<String, Long> activeAlerts = mActiveAlerts; 504 mActiveAlerts = Maps.newHashMap(); 505 for (Map.Entry<String, Long> entry : activeAlerts.entrySet()) { 506 setInterfaceAlert(entry.getKey(), entry.getValue()); 507 } 508 } 509 510 size = mUidRejectOnQuota.size(); 511 if (size > 0) { 512 Slog.d(TAG, "pushing " + size + " active uid rules"); 513 final SparseBooleanArray uidRejectOnQuota = mUidRejectOnQuota; 514 mUidRejectOnQuota = new SparseBooleanArray(); 515 for (int i = 0; i < uidRejectOnQuota.size(); i++) { 516 setUidNetworkRules(uidRejectOnQuota.keyAt(i), uidRejectOnQuota.valueAt(i)); 517 } 518 } 519 } 520 521 // TODO: Push any existing firewall state 522 setFirewallEnabled(mFirewallEnabled || LockdownVpnTracker.isEnabled()); 523 } 524 525 /** 526 * Notify our observers of a new or updated interface address. 527 */ 528 private void notifyAddressUpdated(String iface, LinkAddress address) { 529 final int length = mObservers.beginBroadcast(); 530 try { 531 for (int i = 0; i < length; i++) { 532 try { 533 mObservers.getBroadcastItem(i).addressUpdated(iface, address); 534 } catch (RemoteException e) { 535 } catch (RuntimeException e) { 536 } 537 } 538 } finally { 539 mObservers.finishBroadcast(); 540 } 541 } 542 543 /** 544 * Notify our observers of a deleted interface address. 545 */ 546 private void notifyAddressRemoved(String iface, LinkAddress address) { 547 final int length = mObservers.beginBroadcast(); 548 try { 549 for (int i = 0; i < length; i++) { 550 try { 551 mObservers.getBroadcastItem(i).addressRemoved(iface, address); 552 } catch (RemoteException e) { 553 } catch (RuntimeException e) { 554 } 555 } 556 } finally { 557 mObservers.finishBroadcast(); 558 } 559 } 560 561 /** 562 * Notify our observers of DNS server information received. 563 */ 564 private void notifyInterfaceDnsServerInfo(String iface, long lifetime, String[] addresses) { 565 final int length = mObservers.beginBroadcast(); 566 try { 567 for (int i = 0; i < length; i++) { 568 try { 569 mObservers.getBroadcastItem(i).interfaceDnsServerInfo(iface, lifetime, 570 addresses); 571 } catch (RemoteException e) { 572 } catch (RuntimeException e) { 573 } 574 } 575 } finally { 576 mObservers.finishBroadcast(); 577 } 578 } 579 580 // 581 // Netd Callback handling 582 // 583 584 private class NetdCallbackReceiver implements INativeDaemonConnectorCallbacks { 585 @Override 586 public void onDaemonConnected() { 587 // event is dispatched from internal NDC thread, so we prepare the 588 // daemon back on main thread. 589 if (mConnectedSignal != null) { 590 mConnectedSignal.countDown(); 591 mConnectedSignal = null; 592 } else { 593 mFgHandler.post(new Runnable() { 594 @Override 595 public void run() { 596 prepareNativeDaemon(); 597 } 598 }); 599 } 600 } 601 602 @Override 603 public boolean onCheckHoldWakeLock(int code) { 604 return code == NetdResponseCode.InterfaceClassActivity; 605 } 606 607 @Override 608 public boolean onEvent(int code, String raw, String[] cooked) { 609 String errorMessage = String.format("Invalid event from daemon (%s)", raw); 610 switch (code) { 611 case NetdResponseCode.InterfaceChange: 612 /* 613 * a network interface change occured 614 * Format: "NNN Iface added <name>" 615 * "NNN Iface removed <name>" 616 * "NNN Iface changed <name> <up/down>" 617 * "NNN Iface linkstatus <name> <up/down>" 618 */ 619 if (cooked.length < 4 || !cooked[1].equals("Iface")) { 620 throw new IllegalStateException(errorMessage); 621 } 622 if (cooked[2].equals("added")) { 623 notifyInterfaceAdded(cooked[3]); 624 return true; 625 } else if (cooked[2].equals("removed")) { 626 notifyInterfaceRemoved(cooked[3]); 627 return true; 628 } else if (cooked[2].equals("changed") && cooked.length == 5) { 629 notifyInterfaceStatusChanged(cooked[3], cooked[4].equals("up")); 630 return true; 631 } else if (cooked[2].equals("linkstate") && cooked.length == 5) { 632 notifyInterfaceLinkStateChanged(cooked[3], cooked[4].equals("up")); 633 return true; 634 } 635 throw new IllegalStateException(errorMessage); 636 // break; 637 case NetdResponseCode.BandwidthControl: 638 /* 639 * Bandwidth control needs some attention 640 * Format: "NNN limit alert <alertName> <ifaceName>" 641 */ 642 if (cooked.length < 5 || !cooked[1].equals("limit")) { 643 throw new IllegalStateException(errorMessage); 644 } 645 if (cooked[2].equals("alert")) { 646 notifyLimitReached(cooked[3], cooked[4]); 647 return true; 648 } 649 throw new IllegalStateException(errorMessage); 650 // break; 651 case NetdResponseCode.InterfaceClassActivity: 652 /* 653 * An network interface class state changed (active/idle) 654 * Format: "NNN IfaceClass <active/idle> <label>" 655 */ 656 if (cooked.length < 4 || !cooked[1].equals("IfaceClass")) { 657 throw new IllegalStateException(errorMessage); 658 } 659 long timestampNanos = 0; 660 if (cooked.length == 5) { 661 try { 662 timestampNanos = Long.parseLong(cooked[4]); 663 } catch(NumberFormatException ne) {} 664 } else { 665 timestampNanos = SystemClock.elapsedRealtimeNanos(); 666 } 667 boolean isActive = cooked[2].equals("active"); 668 notifyInterfaceClassActivity(Integer.parseInt(cooked[3]), 669 isActive ? DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH 670 : DataConnectionRealTimeInfo.DC_POWER_STATE_LOW, timestampNanos, false); 671 return true; 672 // break; 673 case NetdResponseCode.InterfaceAddressChange: 674 /* 675 * A network address change occurred 676 * Format: "NNN Address updated <addr> <iface> <flags> <scope>" 677 * "NNN Address removed <addr> <iface> <flags> <scope>" 678 */ 679 if (cooked.length < 7 || !cooked[1].equals("Address")) { 680 throw new IllegalStateException(errorMessage); 681 } 682 683 String iface = cooked[4]; 684 LinkAddress address; 685 try { 686 int flags = Integer.parseInt(cooked[5]); 687 int scope = Integer.parseInt(cooked[6]); 688 address = new LinkAddress(cooked[3], flags, scope); 689 } catch(NumberFormatException e) { // Non-numeric lifetime or scope. 690 throw new IllegalStateException(errorMessage, e); 691 } catch(IllegalArgumentException e) { // Malformed/invalid IP address. 692 throw new IllegalStateException(errorMessage, e); 693 } 694 695 if (cooked[2].equals("updated")) { 696 notifyAddressUpdated(iface, address); 697 } else { 698 notifyAddressRemoved(iface, address); 699 } 700 return true; 701 // break; 702 case NetdResponseCode.InterfaceDnsServerInfo: 703 /* 704 * Information about available DNS servers has been received. 705 * Format: "NNN DnsInfo servers <interface> <lifetime> <servers>" 706 */ 707 long lifetime; // Actually a 32-bit unsigned integer. 708 709 if (cooked.length == 6 && 710 cooked[1].equals("DnsInfo") && 711 cooked[2].equals("servers")) { 712 try { 713 lifetime = Long.parseLong(cooked[4]); 714 } catch (NumberFormatException e) { 715 throw new IllegalStateException(errorMessage); 716 } 717 String[] servers = cooked[5].split(","); 718 notifyInterfaceDnsServerInfo(cooked[3], lifetime, servers); 719 } 720 return true; 721 // break; 722 default: break; 723 } 724 return false; 725 } 726 } 727 728 729 // 730 // INetworkManagementService members 731 // 732 733 @Override 734 public String[] listInterfaces() { 735 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 736 try { 737 return NativeDaemonEvent.filterMessageList( 738 mConnector.executeForList("interface", "list"), InterfaceListResult); 739 } catch (NativeDaemonConnectorException e) { 740 throw e.rethrowAsParcelableException(); 741 } 742 } 743 744 @Override 745 public InterfaceConfiguration getInterfaceConfig(String iface) { 746 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 747 748 final NativeDaemonEvent event; 749 try { 750 event = mConnector.execute("interface", "getcfg", iface); 751 } catch (NativeDaemonConnectorException e) { 752 throw e.rethrowAsParcelableException(); 753 } 754 755 event.checkCode(InterfaceGetCfgResult); 756 757 // Rsp: 213 xx:xx:xx:xx:xx:xx yyy.yyy.yyy.yyy zzz flag1 flag2 flag3 758 final StringTokenizer st = new StringTokenizer(event.getMessage()); 759 760 InterfaceConfiguration cfg; 761 try { 762 cfg = new InterfaceConfiguration(); 763 cfg.setHardwareAddress(st.nextToken(" ")); 764 InetAddress addr = null; 765 int prefixLength = 0; 766 try { 767 addr = NetworkUtils.numericToInetAddress(st.nextToken()); 768 } catch (IllegalArgumentException iae) { 769 Slog.e(TAG, "Failed to parse ipaddr", iae); 770 } 771 772 try { 773 prefixLength = Integer.parseInt(st.nextToken()); 774 } catch (NumberFormatException nfe) { 775 Slog.e(TAG, "Failed to parse prefixLength", nfe); 776 } 777 778 cfg.setLinkAddress(new LinkAddress(addr, prefixLength)); 779 while (st.hasMoreTokens()) { 780 cfg.setFlag(st.nextToken()); 781 } 782 } catch (NoSuchElementException nsee) { 783 throw new IllegalStateException("Invalid response from daemon: " + event); 784 } 785 return cfg; 786 } 787 788 @Override 789 public void setInterfaceConfig(String iface, InterfaceConfiguration cfg) { 790 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 791 LinkAddress linkAddr = cfg.getLinkAddress(); 792 if (linkAddr == null || linkAddr.getAddress() == null) { 793 throw new IllegalStateException("Null LinkAddress given"); 794 } 795 796 final Command cmd = new Command("interface", "setcfg", iface, 797 linkAddr.getAddress().getHostAddress(), 798 linkAddr.getPrefixLength()); 799 for (String flag : cfg.getFlags()) { 800 cmd.appendArg(flag); 801 } 802 803 try { 804 mConnector.execute(cmd); 805 } catch (NativeDaemonConnectorException e) { 806 throw e.rethrowAsParcelableException(); 807 } 808 } 809 810 @Override 811 public void setInterfaceDown(String iface) { 812 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 813 final InterfaceConfiguration ifcg = getInterfaceConfig(iface); 814 ifcg.setInterfaceDown(); 815 setInterfaceConfig(iface, ifcg); 816 } 817 818 @Override 819 public void setInterfaceUp(String iface) { 820 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 821 final InterfaceConfiguration ifcg = getInterfaceConfig(iface); 822 ifcg.setInterfaceUp(); 823 setInterfaceConfig(iface, ifcg); 824 } 825 826 @Override 827 public void setInterfaceIpv6PrivacyExtensions(String iface, boolean enable) { 828 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 829 try { 830 mConnector.execute( 831 "interface", "ipv6privacyextensions", iface, enable ? "enable" : "disable"); 832 } catch (NativeDaemonConnectorException e) { 833 throw e.rethrowAsParcelableException(); 834 } 835 } 836 837 /* TODO: This is right now a IPv4 only function. Works for wifi which loses its 838 IPv6 addresses on interface down, but we need to do full clean up here */ 839 @Override 840 public void clearInterfaceAddresses(String iface) { 841 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 842 try { 843 mConnector.execute("interface", "clearaddrs", iface); 844 } catch (NativeDaemonConnectorException e) { 845 throw e.rethrowAsParcelableException(); 846 } 847 } 848 849 @Override 850 public void enableIpv6(String iface) { 851 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 852 try { 853 mConnector.execute("interface", "ipv6", iface, "enable"); 854 } catch (NativeDaemonConnectorException e) { 855 throw e.rethrowAsParcelableException(); 856 } 857 } 858 859 @Override 860 public void disableIpv6(String iface) { 861 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 862 try { 863 mConnector.execute("interface", "ipv6", iface, "disable"); 864 } catch (NativeDaemonConnectorException e) { 865 throw e.rethrowAsParcelableException(); 866 } 867 } 868 869 @Override 870 public void addRoute(int netId, RouteInfo route) { 871 modifyRoute(netId, ADD, route); 872 } 873 874 @Override 875 public void removeRoute(int netId, RouteInfo route) { 876 modifyRoute(netId, REMOVE, route); 877 } 878 879 private void modifyRoute(int netId, String action, RouteInfo route) { 880 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 881 882 final Command cmd = new Command("network", "route", action, netId); 883 884 // create triplet: interface dest-ip-addr/prefixlength gateway-ip-addr 885 final LinkAddress la = route.getDestination(); 886 cmd.appendArg(route.getInterface()); 887 cmd.appendArg(la.getAddress().getHostAddress() + "/" + la.getPrefixLength()); 888 if (route.hasGateway()) { 889 cmd.appendArg(route.getGateway().getHostAddress()); 890 } 891 892 try { 893 mConnector.execute(cmd); 894 } catch (NativeDaemonConnectorException e) { 895 throw e.rethrowAsParcelableException(); 896 } 897 } 898 899 private ArrayList<String> readRouteList(String filename) { 900 FileInputStream fstream = null; 901 ArrayList<String> list = new ArrayList<String>(); 902 903 try { 904 fstream = new FileInputStream(filename); 905 DataInputStream in = new DataInputStream(fstream); 906 BufferedReader br = new BufferedReader(new InputStreamReader(in)); 907 String s; 908 909 // throw away the title line 910 911 while (((s = br.readLine()) != null) && (s.length() != 0)) { 912 list.add(s); 913 } 914 } catch (IOException ex) { 915 // return current list, possibly empty 916 } finally { 917 if (fstream != null) { 918 try { 919 fstream.close(); 920 } catch (IOException ex) {} 921 } 922 } 923 924 return list; 925 } 926 927 @Override 928 public RouteInfo[] getRoutes(String interfaceName) { 929 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 930 ArrayList<RouteInfo> routes = new ArrayList<RouteInfo>(); 931 932 // v4 routes listed as: 933 // iface dest-addr gateway-addr flags refcnt use metric netmask mtu window IRTT 934 for (String s : readRouteList("/proc/net/route")) { 935 String[] fields = s.split("\t"); 936 937 if (fields.length > 7) { 938 String iface = fields[0]; 939 940 if (interfaceName.equals(iface)) { 941 String dest = fields[1]; 942 String gate = fields[2]; 943 String flags = fields[3]; // future use? 944 String mask = fields[7]; 945 try { 946 // address stored as a hex string, ex: 0014A8C0 947 InetAddress destAddr = 948 NetworkUtils.intToInetAddress((int)Long.parseLong(dest, 16)); 949 int prefixLength = 950 NetworkUtils.netmaskIntToPrefixLength( 951 (int)Long.parseLong(mask, 16)); 952 LinkAddress linkAddress = new LinkAddress(destAddr, prefixLength); 953 954 // address stored as a hex string, ex 0014A8C0 955 InetAddress gatewayAddr = 956 NetworkUtils.intToInetAddress((int)Long.parseLong(gate, 16)); 957 958 RouteInfo route = new RouteInfo(linkAddress, gatewayAddr); 959 routes.add(route); 960 } catch (Exception e) { 961 Log.e(TAG, "Error parsing route " + s + " : " + e); 962 continue; 963 } 964 } 965 } 966 } 967 968 // v6 routes listed as: 969 // dest-addr prefixlength ?? ?? gateway-addr ?? ?? ?? ?? iface 970 for (String s : readRouteList("/proc/net/ipv6_route")) { 971 String[]fields = s.split("\\s+"); 972 if (fields.length > 9) { 973 String iface = fields[9].trim(); 974 if (interfaceName.equals(iface)) { 975 String dest = fields[0]; 976 String prefix = fields[1]; 977 String gate = fields[4]; 978 979 try { 980 // prefix length stored as a hex string, ex 40 981 int prefixLength = Integer.parseInt(prefix, 16); 982 983 // address stored as a 32 char hex string 984 // ex fe800000000000000000000000000000 985 InetAddress destAddr = NetworkUtils.hexToInet6Address(dest); 986 LinkAddress linkAddress = new LinkAddress(destAddr, prefixLength); 987 988 InetAddress gateAddr = NetworkUtils.hexToInet6Address(gate); 989 990 RouteInfo route = new RouteInfo(linkAddress, gateAddr); 991 routes.add(route); 992 } catch (Exception e) { 993 Log.e(TAG, "Error parsing route " + s + " : " + e); 994 continue; 995 } 996 } 997 } 998 } 999 return routes.toArray(new RouteInfo[routes.size()]); 1000 } 1001 1002 @Override 1003 public void setMtu(String iface, int mtu) { 1004 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1005 1006 final NativeDaemonEvent event; 1007 try { 1008 event = mConnector.execute("interface", "setmtu", iface, mtu); 1009 } catch (NativeDaemonConnectorException e) { 1010 throw e.rethrowAsParcelableException(); 1011 } 1012 } 1013 1014 @Override 1015 public void shutdown() { 1016 // TODO: remove from aidl if nobody calls externally 1017 mContext.enforceCallingOrSelfPermission(SHUTDOWN, TAG); 1018 1019 Slog.d(TAG, "Shutting down"); 1020 } 1021 1022 @Override 1023 public boolean getIpForwardingEnabled() throws IllegalStateException{ 1024 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1025 1026 final NativeDaemonEvent event; 1027 try { 1028 event = mConnector.execute("ipfwd", "status"); 1029 } catch (NativeDaemonConnectorException e) { 1030 throw e.rethrowAsParcelableException(); 1031 } 1032 1033 // 211 Forwarding enabled 1034 event.checkCode(IpFwdStatusResult); 1035 return event.getMessage().endsWith("enabled"); 1036 } 1037 1038 @Override 1039 public void setIpForwardingEnabled(boolean enable) { 1040 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1041 try { 1042 mConnector.execute("ipfwd", enable ? "enable" : "disable"); 1043 } catch (NativeDaemonConnectorException e) { 1044 throw e.rethrowAsParcelableException(); 1045 } 1046 } 1047 1048 @Override 1049 public void startTethering(String[] dhcpRange) { 1050 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1051 // cmd is "tether start first_start first_stop second_start second_stop ..." 1052 // an odd number of addrs will fail 1053 1054 final Command cmd = new Command("tether", "start"); 1055 for (String d : dhcpRange) { 1056 cmd.appendArg(d); 1057 } 1058 1059 try { 1060 mConnector.execute(cmd); 1061 } catch (NativeDaemonConnectorException e) { 1062 throw e.rethrowAsParcelableException(); 1063 } 1064 } 1065 1066 @Override 1067 public void stopTethering() { 1068 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1069 try { 1070 mConnector.execute("tether", "stop"); 1071 } catch (NativeDaemonConnectorException e) { 1072 throw e.rethrowAsParcelableException(); 1073 } 1074 } 1075 1076 @Override 1077 public boolean isTetheringStarted() { 1078 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1079 1080 final NativeDaemonEvent event; 1081 try { 1082 event = mConnector.execute("tether", "status"); 1083 } catch (NativeDaemonConnectorException e) { 1084 throw e.rethrowAsParcelableException(); 1085 } 1086 1087 // 210 Tethering services started 1088 event.checkCode(TetherStatusResult); 1089 return event.getMessage().endsWith("started"); 1090 } 1091 1092 @Override 1093 public void tetherInterface(String iface) { 1094 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1095 try { 1096 mConnector.execute("tether", "interface", "add", iface); 1097 } catch (NativeDaemonConnectorException e) { 1098 throw e.rethrowAsParcelableException(); 1099 } 1100 } 1101 1102 @Override 1103 public void untetherInterface(String iface) { 1104 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1105 try { 1106 mConnector.execute("tether", "interface", "remove", iface); 1107 } catch (NativeDaemonConnectorException e) { 1108 throw e.rethrowAsParcelableException(); 1109 } 1110 } 1111 1112 @Override 1113 public String[] listTetheredInterfaces() { 1114 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1115 try { 1116 return NativeDaemonEvent.filterMessageList( 1117 mConnector.executeForList("tether", "interface", "list"), 1118 TetherInterfaceListResult); 1119 } catch (NativeDaemonConnectorException e) { 1120 throw e.rethrowAsParcelableException(); 1121 } 1122 } 1123 1124 @Override 1125 public void setDnsForwarders(String[] dns) { 1126 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1127 1128 final Command cmd = new Command("tether", "dns", "set"); 1129 for (String s : dns) { 1130 cmd.appendArg(NetworkUtils.numericToInetAddress(s).getHostAddress()); 1131 } 1132 1133 try { 1134 mConnector.execute(cmd); 1135 } catch (NativeDaemonConnectorException e) { 1136 throw e.rethrowAsParcelableException(); 1137 } 1138 } 1139 1140 @Override 1141 public String[] getDnsForwarders() { 1142 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1143 try { 1144 return NativeDaemonEvent.filterMessageList( 1145 mConnector.executeForList("tether", "dns", "list"), TetherDnsFwdTgtListResult); 1146 } catch (NativeDaemonConnectorException e) { 1147 throw e.rethrowAsParcelableException(); 1148 } 1149 } 1150 1151 private List<InterfaceAddress> excludeLinkLocal(List<InterfaceAddress> addresses) { 1152 ArrayList<InterfaceAddress> filtered = new ArrayList<InterfaceAddress>(addresses.size()); 1153 for (InterfaceAddress ia : addresses) { 1154 if (!ia.getAddress().isLinkLocalAddress()) 1155 filtered.add(ia); 1156 } 1157 return filtered; 1158 } 1159 1160 private void modifyNat(String action, String internalInterface, String externalInterface) 1161 throws SocketException { 1162 final Command cmd = new Command("nat", action, internalInterface, externalInterface); 1163 1164 final NetworkInterface internalNetworkInterface = NetworkInterface.getByName( 1165 internalInterface); 1166 if (internalNetworkInterface == null) { 1167 cmd.appendArg("0"); 1168 } else { 1169 // Don't touch link-local routes, as link-local addresses aren't routable, 1170 // kernel creates link-local routes on all interfaces automatically 1171 List<InterfaceAddress> interfaceAddresses = excludeLinkLocal( 1172 internalNetworkInterface.getInterfaceAddresses()); 1173 cmd.appendArg(interfaceAddresses.size()); 1174 for (InterfaceAddress ia : interfaceAddresses) { 1175 InetAddress addr = NetworkUtils.getNetworkPart( 1176 ia.getAddress(), ia.getNetworkPrefixLength()); 1177 cmd.appendArg(addr.getHostAddress() + "/" + ia.getNetworkPrefixLength()); 1178 } 1179 } 1180 1181 try { 1182 mConnector.execute(cmd); 1183 } catch (NativeDaemonConnectorException e) { 1184 throw e.rethrowAsParcelableException(); 1185 } 1186 } 1187 1188 @Override 1189 public void enableNat(String internalInterface, String externalInterface) { 1190 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1191 try { 1192 modifyNat("enable", internalInterface, externalInterface); 1193 } catch (SocketException e) { 1194 throw new IllegalStateException(e); 1195 } 1196 } 1197 1198 @Override 1199 public void disableNat(String internalInterface, String externalInterface) { 1200 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1201 try { 1202 modifyNat("disable", internalInterface, externalInterface); 1203 } catch (SocketException e) { 1204 throw new IllegalStateException(e); 1205 } 1206 } 1207 1208 @Override 1209 public String[] listTtys() { 1210 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1211 try { 1212 return NativeDaemonEvent.filterMessageList( 1213 mConnector.executeForList("list_ttys"), TtyListResult); 1214 } catch (NativeDaemonConnectorException e) { 1215 throw e.rethrowAsParcelableException(); 1216 } 1217 } 1218 1219 @Override 1220 public void attachPppd( 1221 String tty, String localAddr, String remoteAddr, String dns1Addr, String dns2Addr) { 1222 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1223 try { 1224 mConnector.execute("pppd", "attach", tty, 1225 NetworkUtils.numericToInetAddress(localAddr).getHostAddress(), 1226 NetworkUtils.numericToInetAddress(remoteAddr).getHostAddress(), 1227 NetworkUtils.numericToInetAddress(dns1Addr).getHostAddress(), 1228 NetworkUtils.numericToInetAddress(dns2Addr).getHostAddress()); 1229 } catch (NativeDaemonConnectorException e) { 1230 throw e.rethrowAsParcelableException(); 1231 } 1232 } 1233 1234 @Override 1235 public void detachPppd(String tty) { 1236 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1237 try { 1238 mConnector.execute("pppd", "detach", tty); 1239 } catch (NativeDaemonConnectorException e) { 1240 throw e.rethrowAsParcelableException(); 1241 } 1242 } 1243 1244 @Override 1245 public void startAccessPoint( 1246 WifiConfiguration wifiConfig, String wlanIface) { 1247 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1248 try { 1249 wifiFirmwareReload(wlanIface, "AP"); 1250 if (wifiConfig == null) { 1251 mConnector.execute("softap", "set", wlanIface); 1252 } else { 1253 mConnector.execute("softap", "set", wlanIface, wifiConfig.SSID, 1254 "broadcast", "6", getSecurityType(wifiConfig), 1255 new SensitiveArg(wifiConfig.preSharedKey)); 1256 } 1257 mConnector.execute("softap", "startap"); 1258 } catch (NativeDaemonConnectorException e) { 1259 throw e.rethrowAsParcelableException(); 1260 } 1261 } 1262 1263 private static String getSecurityType(WifiConfiguration wifiConfig) { 1264 switch (wifiConfig.getAuthType()) { 1265 case KeyMgmt.WPA_PSK: 1266 return "wpa-psk"; 1267 case KeyMgmt.WPA2_PSK: 1268 return "wpa2-psk"; 1269 default: 1270 return "open"; 1271 } 1272 } 1273 1274 /* @param mode can be "AP", "STA" or "P2P" */ 1275 @Override 1276 public void wifiFirmwareReload(String wlanIface, String mode) { 1277 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1278 try { 1279 mConnector.execute("softap", "fwreload", wlanIface, mode); 1280 } catch (NativeDaemonConnectorException e) { 1281 throw e.rethrowAsParcelableException(); 1282 } 1283 } 1284 1285 @Override 1286 public void stopAccessPoint(String wlanIface) { 1287 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1288 try { 1289 mConnector.execute("softap", "stopap"); 1290 wifiFirmwareReload(wlanIface, "STA"); 1291 } catch (NativeDaemonConnectorException e) { 1292 throw e.rethrowAsParcelableException(); 1293 } 1294 } 1295 1296 @Override 1297 public void setAccessPoint(WifiConfiguration wifiConfig, String wlanIface) { 1298 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1299 try { 1300 if (wifiConfig == null) { 1301 mConnector.execute("softap", "set", wlanIface); 1302 } else { 1303 mConnector.execute("softap", "set", wlanIface, wifiConfig.SSID, 1304 "broadcast", "6", getSecurityType(wifiConfig), 1305 new SensitiveArg(wifiConfig.preSharedKey)); 1306 } 1307 } catch (NativeDaemonConnectorException e) { 1308 throw e.rethrowAsParcelableException(); 1309 } 1310 } 1311 1312 @Override 1313 public void addIdleTimer(String iface, int timeout, final int type) { 1314 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1315 1316 if (DBG) Slog.d(TAG, "Adding idletimer"); 1317 1318 synchronized (mIdleTimerLock) { 1319 IdleTimerParams params = mActiveIdleTimers.get(iface); 1320 if (params != null) { 1321 // the interface already has idletimer, update network count 1322 params.networkCount++; 1323 return; 1324 } 1325 1326 try { 1327 mConnector.execute("idletimer", "add", iface, Integer.toString(timeout), 1328 Integer.toString(type)); 1329 } catch (NativeDaemonConnectorException e) { 1330 throw e.rethrowAsParcelableException(); 1331 } 1332 mActiveIdleTimers.put(iface, new IdleTimerParams(timeout, type)); 1333 1334 // Networks start up. 1335 if (ConnectivityManager.isNetworkTypeMobile(type)) { 1336 mNetworkActive = false; 1337 } 1338 mDaemonHandler.post(new Runnable() { 1339 @Override public void run() { 1340 notifyInterfaceClassActivity(type, 1341 DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH, 1342 SystemClock.elapsedRealtimeNanos(), false); 1343 } 1344 }); 1345 } 1346 } 1347 1348 @Override 1349 public void removeIdleTimer(String iface) { 1350 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1351 1352 if (DBG) Slog.d(TAG, "Removing idletimer"); 1353 1354 synchronized (mIdleTimerLock) { 1355 final IdleTimerParams params = mActiveIdleTimers.get(iface); 1356 if (params == null || --(params.networkCount) > 0) { 1357 return; 1358 } 1359 1360 try { 1361 mConnector.execute("idletimer", "remove", iface, 1362 Integer.toString(params.timeout), Integer.toString(params.type)); 1363 } catch (NativeDaemonConnectorException e) { 1364 throw e.rethrowAsParcelableException(); 1365 } 1366 mActiveIdleTimers.remove(iface); 1367 mDaemonHandler.post(new Runnable() { 1368 @Override public void run() { 1369 notifyInterfaceClassActivity(params.type, 1370 DataConnectionRealTimeInfo.DC_POWER_STATE_LOW, 1371 SystemClock.elapsedRealtimeNanos(), false); 1372 } 1373 }); 1374 } 1375 } 1376 1377 @Override 1378 public NetworkStats getNetworkStatsSummaryDev() { 1379 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1380 try { 1381 return mStatsFactory.readNetworkStatsSummaryDev(); 1382 } catch (IOException e) { 1383 throw new IllegalStateException(e); 1384 } 1385 } 1386 1387 @Override 1388 public NetworkStats getNetworkStatsSummaryXt() { 1389 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1390 try { 1391 return mStatsFactory.readNetworkStatsSummaryXt(); 1392 } catch (IOException e) { 1393 throw new IllegalStateException(e); 1394 } 1395 } 1396 1397 @Override 1398 public NetworkStats getNetworkStatsDetail() { 1399 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1400 try { 1401 return mStatsFactory.readNetworkStatsDetail(UID_ALL, null, TAG_ALL, null); 1402 } catch (IOException e) { 1403 throw new IllegalStateException(e); 1404 } 1405 } 1406 1407 @Override 1408 public void setInterfaceQuota(String iface, long quotaBytes) { 1409 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1410 1411 // silently discard when control disabled 1412 // TODO: eventually migrate to be always enabled 1413 if (!mBandwidthControlEnabled) return; 1414 1415 synchronized (mQuotaLock) { 1416 if (mActiveQuotas.containsKey(iface)) { 1417 throw new IllegalStateException("iface " + iface + " already has quota"); 1418 } 1419 1420 try { 1421 // TODO: support quota shared across interfaces 1422 mConnector.execute("bandwidth", "setiquota", iface, quotaBytes); 1423 mActiveQuotas.put(iface, quotaBytes); 1424 } catch (NativeDaemonConnectorException e) { 1425 throw e.rethrowAsParcelableException(); 1426 } 1427 } 1428 } 1429 1430 @Override 1431 public void removeInterfaceQuota(String iface) { 1432 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1433 1434 // silently discard when control disabled 1435 // TODO: eventually migrate to be always enabled 1436 if (!mBandwidthControlEnabled) return; 1437 1438 synchronized (mQuotaLock) { 1439 if (!mActiveQuotas.containsKey(iface)) { 1440 // TODO: eventually consider throwing 1441 return; 1442 } 1443 1444 mActiveQuotas.remove(iface); 1445 mActiveAlerts.remove(iface); 1446 1447 try { 1448 // TODO: support quota shared across interfaces 1449 mConnector.execute("bandwidth", "removeiquota", iface); 1450 } catch (NativeDaemonConnectorException e) { 1451 throw e.rethrowAsParcelableException(); 1452 } 1453 } 1454 } 1455 1456 @Override 1457 public void setInterfaceAlert(String iface, long alertBytes) { 1458 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1459 1460 // silently discard when control disabled 1461 // TODO: eventually migrate to be always enabled 1462 if (!mBandwidthControlEnabled) return; 1463 1464 // quick sanity check 1465 if (!mActiveQuotas.containsKey(iface)) { 1466 throw new IllegalStateException("setting alert requires existing quota on iface"); 1467 } 1468 1469 synchronized (mQuotaLock) { 1470 if (mActiveAlerts.containsKey(iface)) { 1471 throw new IllegalStateException("iface " + iface + " already has alert"); 1472 } 1473 1474 try { 1475 // TODO: support alert shared across interfaces 1476 mConnector.execute("bandwidth", "setinterfacealert", iface, alertBytes); 1477 mActiveAlerts.put(iface, alertBytes); 1478 } catch (NativeDaemonConnectorException e) { 1479 throw e.rethrowAsParcelableException(); 1480 } 1481 } 1482 } 1483 1484 @Override 1485 public void removeInterfaceAlert(String iface) { 1486 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1487 1488 // silently discard when control disabled 1489 // TODO: eventually migrate to be always enabled 1490 if (!mBandwidthControlEnabled) return; 1491 1492 synchronized (mQuotaLock) { 1493 if (!mActiveAlerts.containsKey(iface)) { 1494 // TODO: eventually consider throwing 1495 return; 1496 } 1497 1498 try { 1499 // TODO: support alert shared across interfaces 1500 mConnector.execute("bandwidth", "removeinterfacealert", iface); 1501 mActiveAlerts.remove(iface); 1502 } catch (NativeDaemonConnectorException e) { 1503 throw e.rethrowAsParcelableException(); 1504 } 1505 } 1506 } 1507 1508 @Override 1509 public void setGlobalAlert(long alertBytes) { 1510 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1511 1512 // silently discard when control disabled 1513 // TODO: eventually migrate to be always enabled 1514 if (!mBandwidthControlEnabled) return; 1515 1516 try { 1517 mConnector.execute("bandwidth", "setglobalalert", alertBytes); 1518 } catch (NativeDaemonConnectorException e) { 1519 throw e.rethrowAsParcelableException(); 1520 } 1521 } 1522 1523 @Override 1524 public void setUidNetworkRules(int uid, boolean rejectOnQuotaInterfaces) { 1525 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1526 1527 // silently discard when control disabled 1528 // TODO: eventually migrate to be always enabled 1529 if (!mBandwidthControlEnabled) return; 1530 1531 synchronized (mQuotaLock) { 1532 final boolean oldRejectOnQuota = mUidRejectOnQuota.get(uid, false); 1533 if (oldRejectOnQuota == rejectOnQuotaInterfaces) { 1534 // TODO: eventually consider throwing 1535 return; 1536 } 1537 1538 try { 1539 mConnector.execute("bandwidth", 1540 rejectOnQuotaInterfaces ? "addnaughtyapps" : "removenaughtyapps", uid); 1541 if (rejectOnQuotaInterfaces) { 1542 mUidRejectOnQuota.put(uid, true); 1543 } else { 1544 mUidRejectOnQuota.delete(uid); 1545 } 1546 } catch (NativeDaemonConnectorException e) { 1547 throw e.rethrowAsParcelableException(); 1548 } 1549 } 1550 } 1551 1552 @Override 1553 public boolean isBandwidthControlEnabled() { 1554 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1555 return mBandwidthControlEnabled; 1556 } 1557 1558 @Override 1559 public NetworkStats getNetworkStatsUidDetail(int uid) { 1560 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1561 try { 1562 return mStatsFactory.readNetworkStatsDetail(uid, null, TAG_ALL, null); 1563 } catch (IOException e) { 1564 throw new IllegalStateException(e); 1565 } 1566 } 1567 1568 @Override 1569 public NetworkStats getNetworkStatsTethering() { 1570 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1571 1572 final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 1); 1573 try { 1574 final NativeDaemonEvent[] events = mConnector.executeForList( 1575 "bandwidth", "gettetherstats"); 1576 for (NativeDaemonEvent event : events) { 1577 if (event.getCode() != TetheringStatsListResult) continue; 1578 1579 // 114 ifaceIn ifaceOut rx_bytes rx_packets tx_bytes tx_packets 1580 final StringTokenizer tok = new StringTokenizer(event.getMessage()); 1581 try { 1582 final String ifaceIn = tok.nextToken(); 1583 final String ifaceOut = tok.nextToken(); 1584 1585 final NetworkStats.Entry entry = new NetworkStats.Entry(); 1586 entry.iface = ifaceOut; 1587 entry.uid = UID_TETHERING; 1588 entry.set = SET_DEFAULT; 1589 entry.tag = TAG_NONE; 1590 entry.rxBytes = Long.parseLong(tok.nextToken()); 1591 entry.rxPackets = Long.parseLong(tok.nextToken()); 1592 entry.txBytes = Long.parseLong(tok.nextToken()); 1593 entry.txPackets = Long.parseLong(tok.nextToken()); 1594 stats.combineValues(entry); 1595 } catch (NoSuchElementException e) { 1596 throw new IllegalStateException("problem parsing tethering stats: " + event); 1597 } catch (NumberFormatException e) { 1598 throw new IllegalStateException("problem parsing tethering stats: " + event); 1599 } 1600 } 1601 } catch (NativeDaemonConnectorException e) { 1602 throw e.rethrowAsParcelableException(); 1603 } 1604 return stats; 1605 } 1606 1607 @Override 1608 public void setDnsServersForNetwork(int netId, String[] servers, String domains) { 1609 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1610 1611 final Command cmd = new Command("resolver", "setnetdns", netId, 1612 (domains == null ? "" : domains)); 1613 1614 for (String s : servers) { 1615 InetAddress a = NetworkUtils.numericToInetAddress(s); 1616 if (a.isAnyLocalAddress() == false) { 1617 cmd.appendArg(a.getHostAddress()); 1618 } 1619 } 1620 1621 try { 1622 mConnector.execute(cmd); 1623 } catch (NativeDaemonConnectorException e) { 1624 throw e.rethrowAsParcelableException(); 1625 } 1626 } 1627 1628 @Override 1629 public void setUidRangeRoute(String iface, int uid_start, int uid_end, boolean forward_dns) { 1630 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1631 try { 1632 mConnector.execute("interface", "fwmark", 1633 "uid", "add", iface, uid_start, uid_end, forward_dns ? 1 : 0); 1634 } catch (NativeDaemonConnectorException e) { 1635 throw e.rethrowAsParcelableException(); 1636 } 1637 } 1638 1639 @Override 1640 public void clearUidRangeRoute(String iface, int uid_start, int uid_end) { 1641 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1642 try { 1643 mConnector.execute("interface", "fwmark", 1644 "uid", "remove", iface, uid_start, uid_end, 0); 1645 } catch (NativeDaemonConnectorException e) { 1646 throw e.rethrowAsParcelableException(); 1647 } 1648 } 1649 1650 @Override 1651 public void setMarkedForwarding(String iface) { 1652 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1653 try { 1654 mConnector.execute("interface", "fwmark", "rule", "add", iface); 1655 } catch (NativeDaemonConnectorException e) { 1656 throw e.rethrowAsParcelableException(); 1657 } 1658 } 1659 1660 @Override 1661 public void clearMarkedForwarding(String iface) { 1662 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1663 try { 1664 mConnector.execute("interface", "fwmark", "rule", "remove", iface); 1665 } catch (NativeDaemonConnectorException e) { 1666 throw e.rethrowAsParcelableException(); 1667 } 1668 } 1669 1670 @Override 1671 public int getMarkForUid(int uid) { 1672 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1673 final NativeDaemonEvent event; 1674 try { 1675 event = mConnector.execute("interface", "fwmark", "get", "mark", uid); 1676 } catch (NativeDaemonConnectorException e) { 1677 throw e.rethrowAsParcelableException(); 1678 } 1679 event.checkCode(GetMarkResult); 1680 return Integer.parseInt(event.getMessage()); 1681 } 1682 1683 @Override 1684 public int getMarkForProtect() { 1685 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1686 final NativeDaemonEvent event; 1687 try { 1688 event = mConnector.execute("interface", "fwmark", "get", "protect"); 1689 } catch (NativeDaemonConnectorException e) { 1690 throw e.rethrowAsParcelableException(); 1691 } 1692 event.checkCode(GetMarkResult); 1693 return Integer.parseInt(event.getMessage()); 1694 } 1695 1696 @Override 1697 public void setMarkedForwardingRoute(String iface, RouteInfo route) { 1698 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1699 try { 1700 LinkAddress dest = route.getDestination(); 1701 mConnector.execute("interface", "fwmark", "route", "add", iface, 1702 dest.getAddress().getHostAddress(), dest.getPrefixLength()); 1703 } catch (NativeDaemonConnectorException e) { 1704 throw e.rethrowAsParcelableException(); 1705 } 1706 } 1707 1708 @Override 1709 public void clearMarkedForwardingRoute(String iface, RouteInfo route) { 1710 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1711 try { 1712 LinkAddress dest = route.getDestination(); 1713 mConnector.execute("interface", "fwmark", "route", "remove", iface, 1714 dest.getAddress().getHostAddress(), dest.getPrefixLength()); 1715 } catch (NativeDaemonConnectorException e) { 1716 throw e.rethrowAsParcelableException(); 1717 } 1718 } 1719 1720 @Override 1721 public void setHostExemption(LinkAddress host) { 1722 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1723 try { 1724 mConnector.execute("interface", "fwmark", "exempt", "add", host); 1725 } catch (NativeDaemonConnectorException e) { 1726 throw e.rethrowAsParcelableException(); 1727 } 1728 } 1729 1730 @Override 1731 public void clearHostExemption(LinkAddress host) { 1732 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1733 try { 1734 mConnector.execute("interface", "fwmark", "exempt", "remove", host); 1735 } catch (NativeDaemonConnectorException e) { 1736 throw e.rethrowAsParcelableException(); 1737 } 1738 } 1739 1740 @Override 1741 public void flushNetworkDnsCache(int netId) { 1742 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1743 try { 1744 mConnector.execute("resolver", "flushnet", netId); 1745 } catch (NativeDaemonConnectorException e) { 1746 throw e.rethrowAsParcelableException(); 1747 } 1748 } 1749 1750 @Override 1751 public void setFirewallEnabled(boolean enabled) { 1752 enforceSystemUid(); 1753 try { 1754 mConnector.execute("firewall", enabled ? "enable" : "disable"); 1755 mFirewallEnabled = enabled; 1756 } catch (NativeDaemonConnectorException e) { 1757 throw e.rethrowAsParcelableException(); 1758 } 1759 } 1760 1761 @Override 1762 public boolean isFirewallEnabled() { 1763 enforceSystemUid(); 1764 return mFirewallEnabled; 1765 } 1766 1767 @Override 1768 public void setFirewallInterfaceRule(String iface, boolean allow) { 1769 enforceSystemUid(); 1770 Preconditions.checkState(mFirewallEnabled); 1771 final String rule = allow ? ALLOW : DENY; 1772 try { 1773 mConnector.execute("firewall", "set_interface_rule", iface, rule); 1774 } catch (NativeDaemonConnectorException e) { 1775 throw e.rethrowAsParcelableException(); 1776 } 1777 } 1778 1779 @Override 1780 public void setFirewallEgressSourceRule(String addr, boolean allow) { 1781 enforceSystemUid(); 1782 Preconditions.checkState(mFirewallEnabled); 1783 final String rule = allow ? ALLOW : DENY; 1784 try { 1785 mConnector.execute("firewall", "set_egress_source_rule", addr, rule); 1786 } catch (NativeDaemonConnectorException e) { 1787 throw e.rethrowAsParcelableException(); 1788 } 1789 } 1790 1791 @Override 1792 public void setFirewallEgressDestRule(String addr, int port, boolean allow) { 1793 enforceSystemUid(); 1794 Preconditions.checkState(mFirewallEnabled); 1795 final String rule = allow ? ALLOW : DENY; 1796 try { 1797 mConnector.execute("firewall", "set_egress_dest_rule", addr, port, rule); 1798 } catch (NativeDaemonConnectorException e) { 1799 throw e.rethrowAsParcelableException(); 1800 } 1801 } 1802 1803 @Override 1804 public void setFirewallUidRule(int uid, boolean allow) { 1805 enforceSystemUid(); 1806 Preconditions.checkState(mFirewallEnabled); 1807 final String rule = allow ? ALLOW : DENY; 1808 try { 1809 mConnector.execute("firewall", "set_uid_rule", uid, rule); 1810 } catch (NativeDaemonConnectorException e) { 1811 throw e.rethrowAsParcelableException(); 1812 } 1813 } 1814 1815 private static void enforceSystemUid() { 1816 final int uid = Binder.getCallingUid(); 1817 if (uid != Process.SYSTEM_UID) { 1818 throw new SecurityException("Only available to AID_SYSTEM"); 1819 } 1820 } 1821 1822 @Override 1823 public void startClatd(String interfaceName) throws IllegalStateException { 1824 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1825 1826 try { 1827 mConnector.execute("clatd", "start", interfaceName); 1828 } catch (NativeDaemonConnectorException e) { 1829 throw e.rethrowAsParcelableException(); 1830 } 1831 } 1832 1833 @Override 1834 public void stopClatd() throws IllegalStateException { 1835 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1836 1837 try { 1838 mConnector.execute("clatd", "stop"); 1839 } catch (NativeDaemonConnectorException e) { 1840 throw e.rethrowAsParcelableException(); 1841 } 1842 } 1843 1844 @Override 1845 public boolean isClatdStarted() { 1846 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1847 1848 final NativeDaemonEvent event; 1849 try { 1850 event = mConnector.execute("clatd", "status"); 1851 } catch (NativeDaemonConnectorException e) { 1852 throw e.rethrowAsParcelableException(); 1853 } 1854 1855 event.checkCode(ClatdStatusResult); 1856 return event.getMessage().endsWith("started"); 1857 } 1858 1859 @Override 1860 public void registerNetworkActivityListener(INetworkActivityListener listener) { 1861 mNetworkActivityListeners.register(listener); 1862 } 1863 1864 @Override 1865 public void unregisterNetworkActivityListener(INetworkActivityListener listener) { 1866 mNetworkActivityListeners.unregister(listener); 1867 } 1868 1869 @Override 1870 public boolean isNetworkActive() { 1871 synchronized (mNetworkActivityListeners) { 1872 return mNetworkActive || mActiveIdleTimers.isEmpty(); 1873 } 1874 } 1875 1876 private void reportNetworkActive() { 1877 final int length = mNetworkActivityListeners.beginBroadcast(); 1878 try { 1879 for (int i = 0; i < length; i++) { 1880 try { 1881 mNetworkActivityListeners.getBroadcastItem(i).onNetworkActive(); 1882 } catch (RemoteException e) { 1883 } catch (RuntimeException e) { 1884 } 1885 } 1886 } finally { 1887 mNetworkActivityListeners.finishBroadcast(); 1888 } 1889 } 1890 1891 /** {@inheritDoc} */ 1892 @Override 1893 public void monitor() { 1894 if (mConnector != null) { 1895 mConnector.monitor(); 1896 } 1897 } 1898 1899 @Override 1900 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 1901 mContext.enforceCallingOrSelfPermission(DUMP, TAG); 1902 1903 pw.println("NetworkManagementService NativeDaemonConnector Log:"); 1904 mConnector.dump(fd, pw, args); 1905 pw.println(); 1906 1907 pw.print("Bandwidth control enabled: "); pw.println(mBandwidthControlEnabled); 1908 pw.print("mMobileActivityFromRadio="); pw.print(mMobileActivityFromRadio); 1909 pw.print(" mLastPowerStateFromRadio="); pw.println(mLastPowerStateFromRadio); 1910 pw.print("mNetworkActive="); pw.println(mNetworkActive); 1911 1912 synchronized (mQuotaLock) { 1913 pw.print("Active quota ifaces: "); pw.println(mActiveQuotas.toString()); 1914 pw.print("Active alert ifaces: "); pw.println(mActiveAlerts.toString()); 1915 } 1916 1917 synchronized (mUidRejectOnQuota) { 1918 pw.print("UID reject on quota ifaces: ["); 1919 final int size = mUidRejectOnQuota.size(); 1920 for (int i = 0; i < size; i++) { 1921 pw.print(mUidRejectOnQuota.keyAt(i)); 1922 if (i < size - 1) pw.print(","); 1923 } 1924 pw.println("]"); 1925 } 1926 1927 synchronized (mIdleTimerLock) { 1928 pw.println("Idle timers:"); 1929 for (HashMap.Entry<String, IdleTimerParams> ent : mActiveIdleTimers.entrySet()) { 1930 pw.print(" "); pw.print(ent.getKey()); pw.println(":"); 1931 IdleTimerParams params = ent.getValue(); 1932 pw.print(" timeout="); pw.print(params.timeout); 1933 pw.print(" type="); pw.print(params.type); 1934 pw.print(" networkCount="); pw.println(params.networkCount); 1935 } 1936 } 1937 1938 pw.print("Firewall enabled: "); pw.println(mFirewallEnabled); 1939 } 1940 1941 @Override 1942 public void createNetwork(int netId) { 1943 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1944 1945 try { 1946 mConnector.execute("network", "create", netId); 1947 } catch (NativeDaemonConnectorException e) { 1948 throw e.rethrowAsParcelableException(); 1949 } 1950 } 1951 1952 @Override 1953 public void removeNetwork(int netId) { 1954 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1955 1956 try { 1957 mConnector.execute("network", "destroy", netId); 1958 } catch (NativeDaemonConnectorException e) { 1959 throw e.rethrowAsParcelableException(); 1960 } 1961 } 1962 1963 @Override 1964 public void addInterfaceToNetwork(String iface, int netId) { 1965 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1966 1967 try { 1968 mConnector.execute("network", "addiface", netId, iface); 1969 } catch (NativeDaemonConnectorException e) { 1970 throw e.rethrowAsParcelableException(); 1971 } 1972 } 1973 1974 @Override 1975 public void removeInterfaceFromNetwork(String iface, int netId) { 1976 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1977 1978 try { 1979 mConnector.execute("network", "removeiface", netId, iface); 1980 } catch (NativeDaemonConnectorException e) { 1981 throw e.rethrowAsParcelableException(); 1982 } 1983 } 1984 1985 @Override 1986 public void addLegacyRouteForNetId(int netId, RouteInfo routeInfo, int uid) { 1987 modifyLegacyRouteForNetId(netId, routeInfo, uid, ADD); 1988 } 1989 1990 @Override 1991 public void removeLegacyRouteForNetId(int netId, RouteInfo routeInfo, int uid) { 1992 modifyLegacyRouteForNetId(netId, routeInfo, uid, REMOVE); 1993 } 1994 1995 private void modifyLegacyRouteForNetId(int netId, RouteInfo routeInfo, int uid, String action) { 1996 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1997 1998 final Command cmd = new Command("network", "route", "legacy", uid, action, netId); 1999 2000 // create triplet: interface dest-ip-addr/prefixlength gateway-ip-addr 2001 final LinkAddress la = routeInfo.getDestination(); 2002 cmd.appendArg(routeInfo.getInterface()); 2003 cmd.appendArg(la.getAddress().getHostAddress() + "/" + la.getPrefixLength()); 2004 if (routeInfo.hasGateway()) { 2005 cmd.appendArg(routeInfo.getGateway().getHostAddress()); 2006 } 2007 2008 try { 2009 mConnector.execute(cmd); 2010 } catch (NativeDaemonConnectorException e) { 2011 throw e.rethrowAsParcelableException(); 2012 } 2013 } 2014 2015 @Override 2016 public void setDefaultNetId(int netId) { 2017 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 2018 2019 try { 2020 mConnector.execute("network", "default", "set", netId); 2021 } catch (NativeDaemonConnectorException e) { 2022 throw e.rethrowAsParcelableException(); 2023 } 2024 } 2025 2026 @Override 2027 public void clearDefaultNetId() { 2028 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 2029 2030 try { 2031 mConnector.execute("network", "default", "clear"); 2032 } catch (NativeDaemonConnectorException e) { 2033 throw e.rethrowAsParcelableException(); 2034 } 2035 } 2036 2037 @Override 2038 public void setPermission(boolean internal, boolean changeNetState, int[] uids) { 2039 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 2040 2041 final Command cmd = new Command("network", "permission", "user", "set"); 2042 if (internal) cmd.appendArg(CONNECTIVITY_INTERNAL); 2043 if (changeNetState) cmd.appendArg(CHANGE_NETWORK_STATE); 2044 for (int i=0; i<uids.length; i++) { 2045 cmd.appendArg(uids[i]); 2046 } 2047 2048 try { 2049 mConnector.execute(cmd); 2050 } catch (NativeDaemonConnectorException e) { 2051 throw e.rethrowAsParcelableException(); 2052 } 2053 } 2054 2055 @Override 2056 public void clearPermission(int[] uids) { 2057 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 2058 2059 final Command cmd = new Command("network", "permission", "user", "clear"); 2060 for (int i=0; i<uids.length; i++) { 2061 cmd.appendArg(uids[i]); 2062 } 2063 2064 try { 2065 mConnector.execute(cmd); 2066 } catch (NativeDaemonConnectorException e) { 2067 throw e.rethrowAsParcelableException(); 2068 } 2069 } 2070} 2071