summaryrefslogtreecommitdiff
path: root/service
diff options
context:
space:
mode:
authorRoshan Pius <rpius@google.com>2019-12-10 23:11:53 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2019-12-10 23:11:53 +0000
commitb647449216e4d202fcadd327e6c603a95dd7723c (patch)
tree2487b010d67b6cb50fb0380297be53a02a718400 /service
parent65262bc0def1b44cdcf385456184534cb8b53ef8 (diff)
parent520ff1c59262a21c36f14a3825e665413e91b2c9 (diff)
Merge changes from topic "nw_mgmt_svc"
* changes: wifi: Create local wrapper for INetworkManagementService Wifi: Handle SystemService events in wifi service threads
Diffstat (limited to 'service')
-rw-r--r--service/Android.bp1
-rw-r--r--service/jarjar-rules-shared.txt3
-rw-r--r--service/java/com/android/server/wifi/ClientModeImpl.java12
-rw-r--r--service/java/com/android/server/wifi/WifiInjector.java18
-rw-r--r--service/java/com/android/server/wifi/WifiNative.java55
-rw-r--r--service/java/com/android/server/wifi/WifiServiceImpl.java110
-rw-r--r--service/java/com/android/server/wifi/aware/WifiAwareDataPathStateManager.java19
-rw-r--r--service/java/com/android/server/wifi/aware/WifiAwareService.java3
-rw-r--r--service/java/com/android/server/wifi/aware/WifiAwareServiceImpl.java45
-rw-r--r--service/java/com/android/server/wifi/aware/WifiAwareStateManager.java5
-rw-r--r--service/java/com/android/server/wifi/p2p/WifiP2pServiceImpl.java44
-rw-r--r--service/java/com/android/server/wifi/rtt/RttServiceImpl.java100
-rw-r--r--service/java/com/android/server/wifi/scanner/WifiScanningServiceImpl.java23
-rw-r--r--service/java/com/android/server/wifi/util/NetdWrapper.java489
14 files changed, 706 insertions, 221 deletions
diff --git a/service/Android.bp b/service/Android.bp
index 219321022..a90128b4f 100644
--- a/service/Android.bp
+++ b/service/Android.bp
@@ -124,6 +124,7 @@ java_library {
// the necessary core platform APIs.
"libprotobuf-java-lite",
"libnanohttpd",
+ "netd_aidl_interface-V2-java",
"services.net",
"wifi_proto_scorecard",
"wifi_proto_metrics",
diff --git a/service/jarjar-rules-shared.txt b/service/jarjar-rules-shared.txt
index f17d0c3ac..7faeb64e8 100644
--- a/service/jarjar-rules-shared.txt
+++ b/service/jarjar-rules-shared.txt
@@ -1,3 +1,6 @@
+rule android.net.InterfaceConfigurationParcel* @0
+rule android.net.InterfaceConfiguration* com.android.server.x.wifi.net.InterfaceConfiguration@1
+
# We don't jar-jar the entire package because, we still use some classes (like
# AsyncChannel in com.android.internal.util) from these packages which are not
# inside our jar (currently in framework.jar, but will be in wifisdk.jar in the future).
diff --git a/service/java/com/android/server/wifi/ClientModeImpl.java b/service/java/com/android/server/wifi/ClientModeImpl.java
index 304ad1b87..46d36758f 100644
--- a/service/java/com/android/server/wifi/ClientModeImpl.java
+++ b/service/java/com/android/server/wifi/ClientModeImpl.java
@@ -3103,8 +3103,7 @@ public class ClientModeImpl extends StateMachine {
}
break;
case CMD_INITIALIZE:
- ok = mWifiNative.initialize();
- replyToMessage(message, message.what, ok ? SUCCESS : FAILURE);
+ mWifiNative.initialize();
break;
case CMD_BOOT_COMPLETED:
// get other services that we need to manage
@@ -5560,14 +5559,9 @@ public class ClientModeImpl extends StateMachine {
/**
* Sends a message to initialize the ClientModeImpl.
- *
- * @return true if succeeded, false otherwise.
*/
- public boolean syncInitialize(AsyncChannel channel) {
- Message resultMsg = channel.sendMessageSynchronously(CMD_INITIALIZE);
- boolean result = (resultMsg.arg1 != FAILURE);
- resultMsg.recycle();
- return result;
+ public void initialize() {
+ sendMessage(CMD_INITIALIZE);
}
/**
diff --git a/service/java/com/android/server/wifi/WifiInjector.java b/service/java/com/android/server/wifi/WifiInjector.java
index 0b0a30517..bde949f4f 100644
--- a/service/java/com/android/server/wifi/WifiInjector.java
+++ b/service/java/com/android/server/wifi/WifiInjector.java
@@ -35,7 +35,6 @@ import android.os.Handler;
import android.os.HandlerExecutor;
import android.os.HandlerThread;
import android.os.IBinder;
-import android.os.INetworkManagementService;
import android.os.Looper;
import android.os.Process;
import android.os.SystemProperties;
@@ -56,6 +55,7 @@ import com.android.server.wifi.p2p.WifiP2pMetrics;
import com.android.server.wifi.p2p.WifiP2pMonitor;
import com.android.server.wifi.p2p.WifiP2pNative;
import com.android.server.wifi.rtt.RttMetrics;
+import com.android.server.wifi.util.NetdWrapper;
import com.android.server.wifi.util.TelephonyUtil;
import com.android.server.wifi.util.WifiPermissionsUtil;
import com.android.server.wifi.util.WifiPermissionsWrapper;
@@ -141,7 +141,6 @@ public class WifiInjector {
private final WifiStateTracker mWifiStateTracker;
private final SelfRecovery mSelfRecovery;
private final WakeupController mWakeupController;
- private final INetworkManagementService mNwManagementService;
private final ScanRequestProxy mScanRequestProxy;
private final SarManager mSarManager;
private final BaseWifiDiagnostics mWifiDiagnostics;
@@ -161,6 +160,7 @@ public class WifiInjector {
private final KeyStore mKeyStore;
private final ConnectionFailureNotificationBuilder mConnectionFailureNotificationBuilder;
private final ThroughputPredictor mThroughputPredictor;
+ private NetdWrapper mNetdWrapper;
public WifiInjector(Context context) {
if (context == null) {
@@ -229,13 +229,10 @@ public class WifiInjector {
mWificondControl = new WificondControl(this,
(AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE),
wifiHandler, mClock);
- mNwManagementService = INetworkManagementService.Stub.asInterface(
- mFrameworkFacade.getService(Context.NETWORKMANAGEMENT_SERVICE));
mWifiNative = new WifiNative(
mWifiVendorHal, mSupplicantStaIfaceHal, mHostapdHal, mWificondControl,
- mWifiMonitor, mNwManagementService, mPropertyService, mWifiMetrics,
- mCarrierNetworkConfig,
- wifiHandler, new Random());
+ mWifiMonitor, mPropertyService, mWifiMetrics,
+ mCarrierNetworkConfig, wifiHandler, new Random(), this);
mWifiP2pMonitor = new WifiP2pMonitor(this);
mSupplicantP2pIfaceHal = new SupplicantP2pIfaceHal(mWifiP2pMonitor);
mWifiP2pNative = new WifiP2pNative(
@@ -801,4 +798,11 @@ public class WifiInjector {
public WifiNetworkScoreCache getWifiNetworkScoreCache() {
return mWifiNetworkScoreCache;
}
+
+ public NetdWrapper makeNetdWrapper() {
+ if (mNetdWrapper == null) {
+ mNetdWrapper = new NetdWrapper(mContext, new Handler(mWifiHandlerThread.getLooper()));
+ }
+ return mNetdWrapper;
+ }
}
diff --git a/service/java/com/android/server/wifi/WifiNative.java b/service/java/com/android/server/wifi/WifiNative.java
index 3dde35ed9..5005c1c6c 100644
--- a/service/java/com/android/server/wifi/WifiNative.java
+++ b/service/java/com/android/server/wifi/WifiNative.java
@@ -20,7 +20,6 @@ import static android.net.wifi.WifiManager.WIFI_FEATURE_OWE;
import android.annotation.IntDef;
import android.annotation.NonNull;
-import android.net.InterfaceConfiguration;
import android.net.MacAddress;
import android.net.TrafficStats;
import android.net.apf.ApfCapabilities;
@@ -30,8 +29,6 @@ import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiScanner;
import android.net.wifi.WifiSsid;
import android.os.Handler;
-import android.os.INetworkManagementService;
-import android.os.RemoteException;
import android.os.SystemClock;
import android.text.TextUtils;
import android.util.ArraySet;
@@ -39,11 +36,12 @@ import android.util.Log;
import com.android.internal.annotations.Immutable;
import com.android.internal.util.HexDump;
-import com.android.server.net.BaseNetworkObserver;
import com.android.server.wifi.hotspot2.NetworkDetail;
import com.android.server.wifi.util.FrameParser;
import com.android.server.wifi.util.InformationElementUtil;
import com.android.server.wifi.util.NativeUtil;
+import com.android.server.wifi.util.NetdWrapper;
+import com.android.server.wifi.util.NetdWrapper.NetdEventObserver;
import com.android.server.wifi.util.ScanResultUtil;
import com.android.server.wifi.wificond.NativeScanResult;
import com.android.server.wifi.wificond.RadioChainInfo;
@@ -87,31 +85,32 @@ public class WifiNative {
private final WifiVendorHal mWifiVendorHal;
private final WificondControl mWificondControl;
private final WifiMonitor mWifiMonitor;
- private final INetworkManagementService mNwManagementService;
private final PropertyService mPropertyService;
private final WifiMetrics mWifiMetrics;
private final CarrierNetworkConfig mCarrierNetworkConfig;
private final Handler mHandler;
private final Random mRandom;
+ private final WifiInjector mWifiInjector;
+ private NetdWrapper mNetdWrapper;
private boolean mVerboseLoggingEnabled = false;
public WifiNative(WifiVendorHal vendorHal,
SupplicantStaIfaceHal staIfaceHal, HostapdHal hostapdHal,
WificondControl condControl, WifiMonitor wifiMonitor,
- INetworkManagementService nwService,
PropertyService propertyService, WifiMetrics wifiMetrics,
- CarrierNetworkConfig carrierNetworkConfig, Handler handler, Random random) {
+ CarrierNetworkConfig carrierNetworkConfig, Handler handler, Random random,
+ WifiInjector wifiInjector) {
mWifiVendorHal = vendorHal;
mSupplicantStaIfaceHal = staIfaceHal;
mHostapdHal = hostapdHal;
mWificondControl = condControl;
mWifiMonitor = wifiMonitor;
- mNwManagementService = nwService;
mPropertyService = propertyService;
mWifiMetrics = wifiMetrics;
mCarrierNetworkConfig = carrierNetworkConfig;
mHandler = handler;
mRandom = random;
+ mWifiInjector = wifiInjector;
}
/**
@@ -504,24 +503,14 @@ public class WifiNative {
/** Helper method to register a network observer and return it */
private boolean registerNetworkObserver(NetworkObserverInternal observer) {
if (observer == null) return false;
- try {
- mNwManagementService.registerObserver(observer);
- } catch (RemoteException | IllegalStateException e) {
- Log.e(TAG, "Unable to register observer", e);
- return false;
- }
+ mNetdWrapper.registerObserver(observer);
return true;
}
/** Helper method to unregister a network observer */
private boolean unregisterNetworkObserver(NetworkObserverInternal observer) {
if (observer == null) return false;
- try {
- mNwManagementService.unregisterObserver(observer);
- } catch (RemoteException | IllegalStateException e) {
- Log.e(TAG, "Unable to unregister observer", e);
- return false;
- }
+ mNetdWrapper.unregisterObserver(observer);
return true;
}
@@ -722,7 +711,7 @@ public class WifiNative {
/**
* Network observer to use for all interface up/down notifications.
*/
- private class NetworkObserverInternal extends BaseNetworkObserver {
+ private class NetworkObserverInternal implements NetdEventObserver {
/** Identifier allocated for the interface */
private final int mInterfaceId;
@@ -732,7 +721,7 @@ public class WifiNative {
/**
* Note: We should ideally listen to
- * {@link BaseNetworkObserver#interfaceStatusChanged(String, boolean)} here. But, that
+ * {@link NetdEventObserver#interfaceStatusChanged(String, boolean)} here. But, that
* callback is not working currently (broken in netd). So, instead listen to link state
* change callbacks as triggers to query the real interface state. We should get rid of
* this workaround if we get the |interfaceStatusChanged| callback to work in netd.
@@ -764,6 +753,11 @@ public class WifiNative {
}
});
}
+
+ @Override
+ public void interfaceStatusChanged(String ifaceName, boolean unusedIsLinkUp) {
+ // unused currently. Look at note above.
+ }
}
/**
@@ -909,6 +903,7 @@ public class WifiNative {
}
mWifiVendorHal.registerRadioModeChangeHandler(
new VendorHalRadioModeChangeHandlerInternal());
+ mNetdWrapper = mWifiInjector.makeNetdWrapper();
return true;
}
}
@@ -968,17 +963,17 @@ public class WifiNative {
// IP addresses configured, and this affects
// connectivity when supplicant starts up.
// Ensure we have no IP addresses before a supplicant start.
- mNwManagementService.clearInterfaceAddresses(ifaceName);
+ mNetdWrapper.clearInterfaceAddresses(ifaceName);
// Set privacy extensions
- mNwManagementService.setInterfaceIpv6PrivacyExtensions(ifaceName, true);
+ mNetdWrapper.setInterfaceIpv6PrivacyExtensions(ifaceName, true);
// IPv6 is enabled only as long as access point is connected since:
// - IPv6 addresses and routes stick around after disconnection
// - kernel is unaware when connected and fails to start IPv6 negotiation
// - kernel can start autoconfiguration when 802.1x is not complete
- mNwManagementService.disableIpv6(ifaceName);
- } catch (RemoteException | IllegalStateException e) {
+ mNetdWrapper.disableIpv6(ifaceName);
+ } catch (IllegalStateException e) {
Log.e(TAG, "Unable to change interface settings", e);
}
}
@@ -1248,16 +1243,12 @@ public class WifiNative {
Log.e(TAG, "Trying to get iface state on invalid iface=" + ifaceName);
return false;
}
- InterfaceConfiguration config = null;
try {
- config = mNwManagementService.getInterfaceConfig(ifaceName);
- } catch (RemoteException | IllegalStateException e) {
+ return mNetdWrapper.isInterfaceUp(ifaceName);
+ } catch (IllegalStateException e) {
Log.e(TAG, "Unable to get interface config", e);
- }
- if (config == null) {
return false;
}
- return config.isUp();
}
}
diff --git a/service/java/com/android/server/wifi/WifiServiceImpl.java b/service/java/com/android/server/wifi/WifiServiceImpl.java
index 165df13bc..43a200686 100644
--- a/service/java/com/android/server/wifi/WifiServiceImpl.java
+++ b/service/java/com/android/server/wifi/WifiServiceImpl.java
@@ -310,75 +310,77 @@ public class WifiServiceImpl extends BaseWifiService {
* This function is used only at boot time.
*/
public void checkAndStartWifi() {
- // Check if wi-fi needs to be enabled
- boolean wifiEnabled = mSettingsStore.isWifiToggleEnabled();
- Log.i(TAG, "WifiService starting up with Wi-Fi " + (wifiEnabled ? "enabled" : "disabled"));
-
- registerForScanModeChange();
- mContext.registerReceiver(
- new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- if (mSettingsStore.handleAirplaneModeToggled()) {
- mActiveModeWarden.airplaneModeToggled();
+ mWifiThreadRunner.post(() -> {
+ // Check if wi-fi needs to be enabled
+ boolean wifiEnabled = mSettingsStore.isWifiToggleEnabled();
+ Log.i(TAG,
+ "WifiService starting up with Wi-Fi " + (wifiEnabled ? "enabled" : "disabled"));
+
+ registerForScanModeChange();
+ mContext.registerReceiver(
+ new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (mSettingsStore.handleAirplaneModeToggled()) {
+ mActiveModeWarden.airplaneModeToggled();
+ }
}
- }
- },
- new IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED));
-
- mContext.registerReceiver(
- new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- String state = intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE);
- if (IccCardConstants.INTENT_VALUE_ICC_ABSENT.equals(state)) {
- Log.d(TAG, "resetting networks because SIM was removed");
- mClientModeImpl.resetSimAuthNetworks(false);
- } else if (IccCardConstants.INTENT_VALUE_ICC_LOADED.equals(state)) {
- Log.d(TAG, "resetting networks because SIM was loaded");
- mClientModeImpl.resetSimAuthNetworks(true);
+ },
+ new IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED));
+
+ mContext.registerReceiver(
+ new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ String state = intent.getStringExtra(
+ IccCardConstants.INTENT_KEY_ICC_STATE);
+ if (IccCardConstants.INTENT_VALUE_ICC_ABSENT.equals(state)) {
+ Log.d(TAG, "resetting networks because SIM was removed");
+ mClientModeImpl.resetSimAuthNetworks(false);
+ } else if (IccCardConstants.INTENT_VALUE_ICC_LOADED.equals(state)) {
+ Log.d(TAG, "resetting networks because SIM was loaded");
+ mClientModeImpl.resetSimAuthNetworks(true);
+ }
}
- }
- },
- new IntentFilter(TelephonyIntents.ACTION_SIM_STATE_CHANGED));
+ },
+ new IntentFilter(TelephonyIntents.ACTION_SIM_STATE_CHANGED));
- // Adding optimizations of only receiving broadcasts when wifi is enabled
- // can result in race conditions when apps toggle wifi in the background
- // without active user involvement. Always receive broadcasts.
- registerForBroadcasts();
- mInIdleMode = mPowerManager.isDeviceIdleMode();
+ // Adding optimizations of only receiving broadcasts when wifi is enabled
+ // can result in race conditions when apps toggle wifi in the background
+ // without active user involvement. Always receive broadcasts.
+ registerForBroadcasts();
+ mInIdleMode = mPowerManager.isDeviceIdleMode();
- if (!mClientModeImpl.syncInitialize(mClientModeImplChannel)) {
- Log.wtf(TAG, "Failed to initialize ClientModeImpl");
- }
- mActiveModeWarden.start();
+ mClientModeImpl.initialize();
+ mActiveModeWarden.start();
+ });
}
public void handleBootCompleted() {
- Log.d(TAG, "Handle boot completed");
-
- // Register for system broadcasts.
- IntentFilter intentFilter = new IntentFilter();
- intentFilter.addAction(Intent.ACTION_USER_REMOVED);
- intentFilter.addAction(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED);
- intentFilter.addAction(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED);
- intentFilter.addAction(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED);
- boolean trackEmergencyCallState = mContext.getResources().getBoolean(
- R.bool.config_wifi_turn_off_during_emergency_call);
- if (trackEmergencyCallState) {
- intentFilter.addAction(TelephonyIntents.ACTION_EMERGENCY_CALL_STATE_CHANGED);
- }
- mContext.registerReceiver(mReceiver, intentFilter);
-
mWifiThreadRunner.post(() -> {
+ Log.d(TAG, "Handle boot completed");
+
+ // Register for system broadcasts.
+ IntentFilter intentFilter = new IntentFilter();
+ intentFilter.addAction(Intent.ACTION_USER_REMOVED);
+ intentFilter.addAction(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED);
+ intentFilter.addAction(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED);
+ intentFilter.addAction(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED);
+ boolean trackEmergencyCallState = mContext.getResources().getBoolean(
+ R.bool.config_wifi_turn_off_during_emergency_call);
+ if (trackEmergencyCallState) {
+ intentFilter.addAction(TelephonyIntents.ACTION_EMERGENCY_CALL_STATE_CHANGED);
+ }
+ mContext.registerReceiver(mReceiver, intentFilter);
+
new MemoryStoreImpl(mContext, mWifiInjector, mWifiInjector.getWifiScoreCard()).start();
if (!mWifiConfigManager.loadFromStore()) {
Log.e(TAG, "Failed to load from config store");
}
mPasspointManager.initializeProvisioner(
mWifiInjector.getPasspointProvisionerHandlerThread().getLooper());
+ mClientModeImpl.handleBootCompleted();
});
- mClientModeImpl.handleBootCompleted();
}
public void handleUserSwitch(int userId) {
diff --git a/service/java/com/android/server/wifi/aware/WifiAwareDataPathStateManager.java b/service/java/com/android/server/wifi/aware/WifiAwareDataPathStateManager.java
index 0bb0131f5..5e07205ab 100644
--- a/service/java/com/android/server/wifi/aware/WifiAwareDataPathStateManager.java
+++ b/service/java/com/android/server/wifi/aware/WifiAwareDataPathStateManager.java
@@ -44,10 +44,7 @@ import android.net.wifi.aware.WifiAwareUtils;
import android.net.wifi.util.HexEncoding;
import android.os.Build;
import android.os.Handler;
-import android.os.IBinder;
-import android.os.INetworkManagementService;
import android.os.Looper;
-import android.os.ServiceManager;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.Log;
@@ -55,6 +52,7 @@ import android.util.Pair;
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.wifi.Clock;
+import com.android.server.wifi.util.NetdWrapper;
import com.android.server.wifi.util.WifiPermissionsUtil;
import com.android.server.wifi.util.WifiPermissionsWrapper;
@@ -117,7 +115,7 @@ public class WifiAwareDataPathStateManager {
private Looper mLooper;
private Handler mHandler;
private WifiAwareNetworkFactory mNetworkFactory;
- public INetworkManagementService mNwService;
+ public NetdWrapper mNetdWrapper;
// internal debug flag to override API check
/* package */ boolean mAllowNdpResponderFromAnyOverride = false;
@@ -132,13 +130,15 @@ public class WifiAwareDataPathStateManager {
* connectivity service.
*/
public void start(Context context, Looper looper, WifiAwareMetrics awareMetrics,
- WifiPermissionsUtil wifiPermissionsUtil, WifiPermissionsWrapper permissionsWrapper) {
+ WifiPermissionsUtil wifiPermissionsUtil, WifiPermissionsWrapper permissionsWrapper,
+ NetdWrapper netdWrapper) {
if (VDBG) Log.v(TAG, "start");
mContext = context;
mAwareMetrics = awareMetrics;
mWifiPermissionsUtil = wifiPermissionsUtil;
mPermissionsWrapper = permissionsWrapper;
+ mNetdWrapper = netdWrapper;
mLooper = looper;
mHandler = new Handler(mLooper);
@@ -159,9 +159,6 @@ public class WifiAwareDataPathStateManager {
mNetworkFactory = new WifiAwareNetworkFactory(looper, context, sNetworkCapabilitiesFilter);
mNetworkFactory.setScoreFilter(NETWORK_FACTORY_SCORE_AVAIL);
mNetworkFactory.register();
-
- IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
- mNwService = INetworkManagementService.Stub.asInterface(b);
}
private Map.Entry<WifiAwareNetworkSpecifier, AwareNetworkRequestInformation>
@@ -568,8 +565,8 @@ public class WifiAwareDataPathStateManager {
boolean interfaceUsedByAnotherNdp = isInterfaceUpAndUsedByAnotherNdp(nnri);
if (!interfaceUsedByAnotherNdp) {
try {
- mNwService.setInterfaceUp(nnri.interfaceName);
- mNwService.enableIpv6(nnri.interfaceName);
+ mNetdWrapper.setInterfaceUp(nnri.interfaceName);
+ mNetdWrapper.enableIpv6(nnri.interfaceName);
} catch (Exception e) { // NwService throws runtime exceptions for errors
Log.e(TAG, "onDataPathConfirm: ACCEPT nnri=" + nnri
+ ": can't configure network - "
@@ -1070,7 +1067,7 @@ public class WifiAwareDataPathStateManager {
}
} else {
try {
- mNwService.setInterfaceDown(nnri.interfaceName);
+ mNetdWrapper.setInterfaceDown(nnri.interfaceName);
} catch (Exception e) { // NwService throws runtime exceptions for errors
Log.e(TAG, "tearDownInterfaceIfPossible: nnri=" + nnri
+ ": can't bring interface down - " + e);
diff --git a/service/java/com/android/server/wifi/aware/WifiAwareService.java b/service/java/com/android/server/wifi/aware/WifiAwareService.java
index f1aa0e4d4..94d8bc77d 100644
--- a/service/java/com/android/server/wifi/aware/WifiAwareService.java
+++ b/service/java/com/android/server/wifi/aware/WifiAwareService.java
@@ -72,7 +72,8 @@ public final class WifiAwareService extends SystemService {
wifiInjector.getWifiMetrics().getWifiAwareMetrics(),
wifiInjector.getWifiPermissionsUtil(),
wifiInjector.getWifiPermissionsWrapper(), wifiInjector.getFrameworkFacade(),
- wifiAwareNativeManager, wifiAwareNativeApi, wifiAwareNativeCallback);
+ wifiAwareNativeManager, wifiAwareNativeApi, wifiAwareNativeCallback,
+ wifiInjector.makeNetdWrapper());
} else if (phase == SystemService.PHASE_BOOT_COMPLETED) {
mImpl.startLate();
}
diff --git a/service/java/com/android/server/wifi/aware/WifiAwareServiceImpl.java b/service/java/com/android/server/wifi/aware/WifiAwareServiceImpl.java
index fbfa50ce0..cd697ceac 100644
--- a/service/java/com/android/server/wifi/aware/WifiAwareServiceImpl.java
+++ b/service/java/com/android/server/wifi/aware/WifiAwareServiceImpl.java
@@ -46,6 +46,7 @@ import android.util.SparseIntArray;
import com.android.server.wifi.Clock;
import com.android.server.wifi.FrameworkFacade;
import com.android.server.wifi.WifiInjector;
+import com.android.server.wifi.util.NetdWrapper;
import com.android.server.wifi.util.WifiPermissionsUtil;
import com.android.server.wifi.util.WifiPermissionsWrapper;
@@ -69,6 +70,7 @@ public class WifiAwareServiceImpl extends IWifiAwareManager.Stub {
private WifiPermissionsUtil mWifiPermissionsUtil;
private WifiAwareStateManager mStateManager;
private WifiAwareShellCommand mShellCommand;
+ private Handler mHandler;
private final Object mLock = new Object();
private final SparseArray<IBinder.DeathRecipient> mDeathRecipientsByClientId =
@@ -98,29 +100,34 @@ public class WifiAwareServiceImpl extends IWifiAwareManager.Stub {
WifiPermissionsUtil wifiPermissionsUtil, WifiPermissionsWrapper permissionsWrapper,
FrameworkFacade frameworkFacade, WifiAwareNativeManager wifiAwareNativeManager,
WifiAwareNativeApi wifiAwareNativeApi,
- WifiAwareNativeCallback wifiAwareNativeCallback) {
+ WifiAwareNativeCallback wifiAwareNativeCallback, NetdWrapper netdWrapper) {
Log.i(TAG, "Starting Wi-Fi Aware service");
mWifiPermissionsUtil = wifiPermissionsUtil;
mStateManager = awareStateManager;
mShellCommand = awareShellCommand;
- mStateManager.start(mContext, handlerThread.getLooper(), awareMetrics, wifiPermissionsUtil,
- permissionsWrapper, new Clock());
-
- frameworkFacade.registerContentObserver(mContext,
- Settings.Global.getUriFor(Settings.Global.WIFI_VERBOSE_LOGGING_ENABLED), true,
- new ContentObserver(new Handler(handlerThread.getLooper())) {
- @Override
- public void onChange(boolean selfChange) {
- enableVerboseLogging(frameworkFacade.getIntegerSetting(mContext,
- Settings.Global.WIFI_VERBOSE_LOGGING_ENABLED, 0), awareStateManager,
- wifiAwareNativeManager, wifiAwareNativeApi,
- wifiAwareNativeCallback);
- }
- });
- enableVerboseLogging(frameworkFacade.getIntegerSetting(mContext,
- Settings.Global.WIFI_VERBOSE_LOGGING_ENABLED, 0), awareStateManager,
- wifiAwareNativeManager, wifiAwareNativeApi, wifiAwareNativeCallback);
+ mHandler = new Handler(handlerThread.getLooper());
+
+ mHandler.post(() -> {
+ mStateManager.start(mContext, handlerThread.getLooper(), awareMetrics,
+ wifiPermissionsUtil, permissionsWrapper, new Clock(), netdWrapper);
+
+ frameworkFacade.registerContentObserver(mContext,
+ Settings.Global.getUriFor(Settings.Global.WIFI_VERBOSE_LOGGING_ENABLED), true,
+ new ContentObserver(new Handler(handlerThread.getLooper())) {
+ @Override
+ public void onChange(boolean selfChange) {
+ enableVerboseLogging(frameworkFacade.getIntegerSetting(mContext,
+ Settings.Global.WIFI_VERBOSE_LOGGING_ENABLED, 0),
+ awareStateManager,
+ wifiAwareNativeManager, wifiAwareNativeApi,
+ wifiAwareNativeCallback);
+ }
+ });
+ enableVerboseLogging(frameworkFacade.getIntegerSetting(mContext,
+ Settings.Global.WIFI_VERBOSE_LOGGING_ENABLED, 0), awareStateManager,
+ wifiAwareNativeManager, wifiAwareNativeApi, wifiAwareNativeCallback);
+ });
}
private void enableVerboseLogging(int verbose, WifiAwareStateManager awareStateManager,
@@ -154,7 +161,7 @@ public class WifiAwareServiceImpl extends IWifiAwareManager.Stub {
public void startLate() {
Log.i(TAG, "Late initialization of Wi-Fi Aware service");
- mStateManager.startLate();
+ mHandler.post(() -> mStateManager.startLate());
}
@Override
diff --git a/service/java/com/android/server/wifi/aware/WifiAwareStateManager.java b/service/java/com/android/server/wifi/aware/WifiAwareStateManager.java
index 924a222ff..bdf1b728e 100644
--- a/service/java/com/android/server/wifi/aware/WifiAwareStateManager.java
+++ b/service/java/com/android/server/wifi/aware/WifiAwareStateManager.java
@@ -55,6 +55,7 @@ import com.android.internal.util.State;
import com.android.internal.util.StateMachine;
import com.android.internal.util.WakeupMessage;
import com.android.server.wifi.Clock;
+import com.android.server.wifi.util.NetdWrapper;
import com.android.server.wifi.util.WifiPermissionsUtil;
import com.android.server.wifi.util.WifiPermissionsWrapper;
@@ -381,7 +382,7 @@ public class WifiAwareStateManager implements WifiAwareShellCommand.DelegatedShe
*/
public void start(Context context, Looper looper, WifiAwareMetrics awareMetrics,
WifiPermissionsUtil wifiPermissionsUtil, WifiPermissionsWrapper permissionsWrapper,
- Clock clock) {
+ Clock clock, NetdWrapper netdWrapper) {
Log.i(TAG, "start()");
mContext = context;
@@ -393,7 +394,7 @@ public class WifiAwareStateManager implements WifiAwareShellCommand.DelegatedShe
mDataPathMgr = new WifiAwareDataPathStateManager(this, clock);
mDataPathMgr.start(mContext, mSm.getHandler().getLooper(), awareMetrics,
- wifiPermissionsUtil, permissionsWrapper);
+ wifiPermissionsUtil, permissionsWrapper, netdWrapper);
mPowerManager = mContext.getSystemService(PowerManager.class);
mLocationManager = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
diff --git a/service/java/com/android/server/wifi/p2p/WifiP2pServiceImpl.java b/service/java/com/android/server/wifi/p2p/WifiP2pServiceImpl.java
index 217adfedc..8f3bb98be 100644
--- a/service/java/com/android/server/wifi/p2p/WifiP2pServiceImpl.java
+++ b/service/java/com/android/server/wifi/p2p/WifiP2pServiceImpl.java
@@ -32,7 +32,6 @@ import android.location.LocationManager;
import android.net.ConnectivityManager;
import android.net.DhcpResults;
import android.net.InetAddresses;
-import android.net.InterfaceConfiguration;
import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.NetworkInfo;
@@ -61,13 +60,11 @@ import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
-import android.os.INetworkManagementService;
import android.os.Looper;
import android.os.Message;
import android.os.Messenger;
import android.os.Process;
import android.os.RemoteException;
-import android.os.ServiceManager;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
@@ -91,6 +88,7 @@ import com.android.server.wifi.FrameworkFacade;
import com.android.server.wifi.WifiInjector;
import com.android.server.wifi.WifiLog;
import com.android.server.wifi.proto.nano.WifiMetricsProto.P2pConnectionEvent;
+import com.android.server.wifi.util.NetdWrapper;
import com.android.server.wifi.util.WifiAsyncChannel;
import com.android.server.wifi.util.WifiHandler;
import com.android.server.wifi.util.WifiPermissionsUtil;
@@ -123,7 +121,7 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub {
private Context mContext;
- INetworkManagementService mNwService;
+ NetdWrapper mNetdWrapper;
private IIpClient mIpClient;
private int mIpClientStartIndex = 0;
private DhcpResults mDhcpResults;
@@ -481,8 +479,7 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub {
* Obtains the service interface for Managements services
*/
public void connectivityServiceReady() {
- IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
- mNwService = INetworkManagementService.Stub.asInterface(b);
+ mNetdWrapper = mWifiInjector.makeNetdWrapper();
}
private void enforceAccessPermission() {
@@ -1412,9 +1409,7 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub {
}
setupInterfaceFeatures(mInterfaceName);
try {
- mNwService.setInterfaceUp(mInterfaceName);
- } catch (RemoteException re) {
- loge("Unable to change interface settings: " + re);
+ mNetdWrapper.setInterfaceUp(mInterfaceName);
} catch (IllegalStateException ie) {
loge("Unable to change interface settings: " + ie);
}
@@ -2735,7 +2730,7 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub {
try {
final String ifname = mGroup.getInterface();
if (mDhcpResults != null) {
- mNwService.addInterfaceToLocalNetwork(
+ mNetdWrapper.addInterfaceToLocalNetwork(
ifname, mDhcpResults.getRoutes(ifname));
}
} catch (Exception e) {
@@ -3093,23 +3088,20 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub {
private void startDhcpServer(String intf) {
if (!isDhcpServerHostedByDnsmasq()) return;
- InterfaceConfiguration ifcg = null;
try {
- ifcg = mNwService.getInterfaceConfig(intf);
- ifcg.setLinkAddress(new LinkAddress(InetAddresses.parseNumericAddress(
- SERVER_ADDRESS), 24));
- ifcg.setInterfaceUp();
- mNwService.setInterfaceConfig(intf, ifcg);
+ mNetdWrapper.setInterfaceLinkAddress(
+ intf,
+ new LinkAddress(InetAddresses.parseNumericAddress(SERVER_ADDRESS), 24));
// This starts the dnsmasq server
ConnectivityManager cm = (ConnectivityManager) mContext.getSystemService(
Context.CONNECTIVITY_SERVICE);
String[] tetheringDhcpRanges = cm.getTetheredDhcpRanges();
- if (mNwService.isTetheringStarted()) {
+ if (mNetdWrapper.isTetheringStarted()) {
if (mVerboseLoggingEnabled) logd("Stop existing tethering and restart it");
- mNwService.stopTethering();
+ mNetdWrapper.stopTethering();
}
- mNwService.tetherInterface(intf);
- mNwService.startTethering(tetheringDhcpRanges);
+ mNetdWrapper.tetherInterface(intf);
+ mNetdWrapper.startTethering(tetheringDhcpRanges);
} catch (Exception e) {
loge("Error configuring interface " + intf + ", :" + e);
return;
@@ -3122,15 +3114,15 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub {
if (!isDhcpServerHostedByDnsmasq()) return;
try {
- mNwService.untetherInterface(intf);
- for (String temp : mNwService.listTetheredInterfaces()) {
+ mNetdWrapper.untetherInterface(intf);
+ for (String temp : mNetdWrapper.listTetheredInterfaces()) {
logd("List all interfaces " + temp);
if (temp.compareTo(intf) != 0) {
logd("Found other tethering interfaces, so keep tethering alive");
return;
}
}
- mNwService.stopTethering();
+ mNetdWrapper.stopTethering();
} catch (Exception e) {
loge("Error stopping Dhcp server" + e);
return;
@@ -3770,14 +3762,14 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub {
if (mVerboseLoggingEnabled) logd("stop IpClient");
stopIpClient();
try {
- mNwService.removeInterfaceFromLocalNetwork(mGroup.getInterface());
- } catch (RemoteException e) {
+ mNetdWrapper.removeInterfaceFromLocalNetwork(mGroup.getInterface());
+ } catch (IllegalStateException e) {
loge("Failed to remove iface from local network " + e);
}
}
try {
- mNwService.clearInterfaceAddresses(mGroup.getInterface());
+ mNetdWrapper.clearInterfaceAddresses(mGroup.getInterface());
} catch (Exception e) {
loge("Failed to clear addresses " + e);
}
diff --git a/service/java/com/android/server/wifi/rtt/RttServiceImpl.java b/service/java/com/android/server/wifi/rtt/RttServiceImpl.java
index 6e35eb5ad..659553656 100644
--- a/service/java/com/android/server/wifi/rtt/RttServiceImpl.java
+++ b/service/java/com/android/server/wifi/rtt/RttServiceImpl.java
@@ -250,67 +250,67 @@ public class RttServiceImpl extends IWifiRttManager.Stub {
mRttMetrics = rttMetrics;
mWifiPermissionsUtil = wifiPermissionsUtil;
mRttServiceSynchronized = new RttServiceSynchronized(looper, rttNative);
-
mActivityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
mPowerManager = mContext.getSystemService(PowerManager.class);
- IntentFilter intentFilter = new IntentFilter();
- intentFilter.addAction(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED);
- mContext.registerReceiver(new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- String action = intent.getAction();
- if (mDbg) Log.v(TAG, "BroadcastReceiver: action=" + action);
- if (PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED.equals(action)) {
- if (mPowerManager.isDeviceIdleMode()) {
- disable();
- } else {
- enableIfPossible();
+ mRttServiceSynchronized.mHandler.post(() -> {
+ IntentFilter intentFilter = new IntentFilter();
+ intentFilter.addAction(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED);
+ mContext.registerReceiver(new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ String action = intent.getAction();
+ if (mDbg) Log.v(TAG, "BroadcastReceiver: action=" + action);
+
+ if (PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED.equals(action)) {
+ if (mPowerManager.isDeviceIdleMode()) {
+ disable();
+ } else {
+ enableIfPossible();
+ }
}
}
- }
- }, intentFilter);
-
- frameworkFacade.registerContentObserver(mContext,
- Settings.Global.getUriFor(Settings.Global.WIFI_VERBOSE_LOGGING_ENABLED), true,
- new ContentObserver(mRttServiceSynchronized.mHandler) {
- @Override
- public void onChange(boolean selfChange) {
- enableVerboseLogging(frameworkFacade.getIntegerSetting(mContext,
- Settings.Global.WIFI_VERBOSE_LOGGING_ENABLED, 0));
- }
- });
+ }, intentFilter);
- enableVerboseLogging(frameworkFacade.getIntegerSetting(mContext,
- Settings.Global.WIFI_VERBOSE_LOGGING_ENABLED, 0));
+ frameworkFacade.registerContentObserver(mContext,
+ Settings.Global.getUriFor(Settings.Global.WIFI_VERBOSE_LOGGING_ENABLED), true,
+ new ContentObserver(mRttServiceSynchronized.mHandler) {
+ @Override
+ public void onChange(boolean selfChange) {
+ enableVerboseLogging(frameworkFacade.getIntegerSetting(mContext,
+ Settings.Global.WIFI_VERBOSE_LOGGING_ENABLED, 0));
+ }
+ });
- frameworkFacade.registerContentObserver(mContext,
- Settings.Global.getUriFor(Settings.Global.WIFI_RTT_BACKGROUND_EXEC_GAP_MS),
- true,
- new ContentObserver(mRttServiceSynchronized.mHandler) {
- @Override
- public void onChange(boolean selfChange) {
- updateBackgroundThrottlingInterval(frameworkFacade);
- }
- });
+ enableVerboseLogging(frameworkFacade.getIntegerSetting(mContext,
+ Settings.Global.WIFI_VERBOSE_LOGGING_ENABLED, 0));
- updateBackgroundThrottlingInterval(frameworkFacade);
+ frameworkFacade.registerContentObserver(mContext,
+ Settings.Global.getUriFor(Settings.Global.WIFI_RTT_BACKGROUND_EXEC_GAP_MS),
+ true,
+ new ContentObserver(mRttServiceSynchronized.mHandler) {
+ @Override
+ public void onChange(boolean selfChange) {
+ updateBackgroundThrottlingInterval(frameworkFacade);
+ }
+ });
- intentFilter = new IntentFilter();
- intentFilter.addAction(LocationManager.MODE_CHANGED_ACTION);
- mContext.registerReceiver(new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- if (mDbg) Log.v(TAG, "onReceive: MODE_CHANGED_ACTION: intent=" + intent);
- if (mWifiPermissionsUtil.isLocationModeEnabled()) {
- enableIfPossible();
- } else {
- disable();
+ updateBackgroundThrottlingInterval(frameworkFacade);
+
+ intentFilter = new IntentFilter();
+ intentFilter.addAction(LocationManager.MODE_CHANGED_ACTION);
+ mContext.registerReceiver(new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (mDbg) Log.v(TAG, "onReceive: MODE_CHANGED_ACTION: intent=" + intent);
+ if (mWifiPermissionsUtil.isLocationModeEnabled()) {
+ enableIfPossible();
+ } else {
+ disable();
+ }
}
- }
- }, intentFilter);
+ }, intentFilter);
- mRttServiceSynchronized.mHandler.post(() -> {
rttNative.start(mRttServiceSynchronized.mHandler);
});
}
diff --git a/service/java/com/android/server/wifi/scanner/WifiScanningServiceImpl.java b/service/java/com/android/server/wifi/scanner/WifiScanningServiceImpl.java
index f6345ec12..bc727591e 100644
--- a/service/java/com/android/server/wifi/scanner/WifiScanningServiceImpl.java
+++ b/service/java/com/android/server/wifi/scanner/WifiScanningServiceImpl.java
@@ -36,6 +36,7 @@ import android.os.BadParcelableException;
import android.os.BatteryStatsManager;
import android.os.Binder;
import android.os.Bundle;
+import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.Messenger;
@@ -404,16 +405,18 @@ public class WifiScanningServiceImpl extends IWifiScanner.Stub {
}
public void startService() {
- mBackgroundScanStateMachine = new WifiBackgroundScanStateMachine(mLooper);
- mSingleScanStateMachine = new WifiSingleScanStateMachine(mLooper);
- mPnoScanStateMachine = new WifiPnoScanStateMachine(mLooper);
-
- mBackgroundScanStateMachine.start();
- mSingleScanStateMachine.start();
- mPnoScanStateMachine.start();
-
- // Create client handler only after StateMachines are ready.
- mClientHandler = new ClientHandler(TAG, mLooper);
+ new Handler(mLooper).post(() -> {
+ mBackgroundScanStateMachine = new WifiBackgroundScanStateMachine(mLooper);
+ mSingleScanStateMachine = new WifiSingleScanStateMachine(mLooper);
+ mPnoScanStateMachine = new WifiPnoScanStateMachine(mLooper);
+
+ mBackgroundScanStateMachine.start();
+ mSingleScanStateMachine.start();
+ mPnoScanStateMachine.start();
+
+ // Create client handler only after StateMachines are ready.
+ mClientHandler = new ClientHandler(TAG, mLooper);
+ });
}
/**
diff --git a/service/java/com/android/server/wifi/util/NetdWrapper.java b/service/java/com/android/server/wifi/util/NetdWrapper.java
new file mode 100644
index 000000000..88d65dd1f
--- /dev/null
+++ b/service/java/com/android/server/wifi/util/NetdWrapper.java
@@ -0,0 +1,489 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wifi.util;
+
+import android.content.Context;
+import android.net.INetd;
+import android.net.INetdUnsolicitedEventListener;
+import android.net.InterfaceConfiguration;
+import android.net.InterfaceConfigurationParcel;
+import android.net.IpPrefix;
+import android.net.LinkAddress;
+import android.net.NetworkUtils;
+import android.net.RouteInfo;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.ServiceSpecificException;
+import android.text.TextUtils;
+import android.util.Log;
+
+import java.net.InetAddress;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * This is a simple wrapper over INetd calls used by wifi stack.
+ *
+ * Based on {@link com.android.server.NetworkManagementService}
+ */
+public class NetdWrapper {
+ private static final String TAG = "NetdWrapper";
+ static final boolean MODIFY_OPERATION_ADD = true;
+ static final boolean MODIFY_OPERATION_REMOVE = false;
+
+ private final INetd mNetdService;
+ private final NetdUnsolicitedEventListener mNetdUnsolicitedEventListener;
+ private final Handler mHandler;
+ private final Set<NetdEventObserver> mObservers = new HashSet<>();
+
+ /**
+ * Observer for iface events.
+ */
+ public interface NetdEventObserver {
+ /**
+ * Interface configuration status has changed.
+ *
+ * @param iface The interface.
+ * @param up True if the interface has been enabled.
+ */
+ void interfaceStatusChanged(String iface, boolean up);
+ /**
+ * Interface physical-layer link state has changed. For Ethernet,
+ * this method is invoked when the cable is plugged in or unplugged.
+ *
+ * @param iface The interface.
+ * @param up True if the physical link-layer connection signal is valid.
+ */
+ void interfaceLinkStateChanged(String iface, boolean up);
+ }
+
+ private class NetdUnsolicitedEventListener extends INetdUnsolicitedEventListener.Stub {
+ @Override
+ public void onInterfaceClassActivityChanged(boolean isActive,
+ int label, long timestamp, int uid) throws RemoteException {
+ // Unused.
+ }
+
+ @Override
+ public void onQuotaLimitReached(String alertName, String ifName)
+ throws RemoteException {
+ // Unused.
+ }
+
+ @Override
+ public void onInterfaceDnsServerInfo(String ifName,
+ long lifetime, String[] servers) throws RemoteException {
+ // Unused.
+ }
+
+ @Override
+ public void onInterfaceAddressUpdated(String addr,
+ String ifName, int flags, int scope) throws RemoteException {
+ // Unused.
+ }
+
+ @Override
+ public void onInterfaceAddressRemoved(String addr,
+ String ifName, int flags, int scope) throws RemoteException {
+ // Unused.
+ }
+
+ @Override
+ public void onInterfaceAdded(String ifName) throws RemoteException {
+ // Unused.
+ }
+
+ @Override
+ public void onInterfaceRemoved(String ifName) throws RemoteException {
+ // Unused.
+ }
+
+ @Override
+ public void onInterfaceChanged(String ifName, boolean up)
+ throws RemoteException {
+ mHandler.post(() -> notifyInterfaceStatusChanged(ifName, up));
+ }
+
+ @Override
+ public void onInterfaceLinkStateChanged(String ifName, boolean up)
+ throws RemoteException {
+ mHandler.post(() -> notifyInterfaceLinkStateChanged(ifName, up));
+ }
+
+ @Override
+ public void onRouteChanged(boolean updated,
+ String route, String gateway, String ifName) throws RemoteException {
+ // Unused.
+ }
+
+ @Override
+ public void onStrictCleartextDetected(int uid, String hex) throws RemoteException {
+ // Unused.
+ }
+
+ @Override
+ public int getInterfaceVersion() {
+ return INetdUnsolicitedEventListener.VERSION;
+ }
+ }
+
+ public NetdWrapper(Context context, Handler handler) {
+ mNetdService = INetd.Stub.asInterface(
+ (IBinder) context.getSystemService(Context.NETD_SERVICE));
+ mNetdUnsolicitedEventListener = new NetdUnsolicitedEventListener();
+ mHandler = handler;
+
+ try {
+ mNetdService.registerUnsolicitedEventListener(mNetdUnsolicitedEventListener);
+ } catch (RemoteException | ServiceSpecificException e) {
+ Log.e(TAG, "Failed to set Netd unsolicited event listener " + e);
+ }
+ }
+
+ private void modifyInterfaceInNetwork(boolean add, int netId, String iface) {
+ try {
+ if (add) {
+ mNetdService.networkAddInterface(netId, iface);
+ } else {
+ mNetdService.networkRemoveInterface(netId, iface);
+ }
+ } catch (RemoteException | ServiceSpecificException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ private void modifyRoute(boolean add, int netId, RouteInfo route) {
+ final String ifName = route.getInterface();
+ final String dst = route.getDestination().toString();
+ final String nextHop;
+
+ switch (route.getType()) {
+ case RouteInfo.RTN_UNICAST:
+ if (route.hasGateway()) {
+ nextHop = route.getGateway().getHostAddress();
+ } else {
+ nextHop = INetd.NEXTHOP_NONE;
+ }
+ break;
+ case RouteInfo.RTN_UNREACHABLE:
+ nextHop = INetd.NEXTHOP_UNREACHABLE;
+ break;
+ case RouteInfo.RTN_THROW:
+ nextHop = INetd.NEXTHOP_THROW;
+ break;
+ default:
+ nextHop = INetd.NEXTHOP_NONE;
+ break;
+ }
+ try {
+ if (add) {
+ mNetdService.networkAddRoute(netId, ifName, dst, nextHop);
+ } else {
+ mNetdService.networkRemoveRoute(netId, ifName, dst, nextHop);
+ }
+ } catch (RemoteException | ServiceSpecificException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ /**
+ * Add iface to local network.
+ */
+ public void addInterfaceToLocalNetwork(String iface, List<RouteInfo> routes) {
+ modifyInterfaceInNetwork(MODIFY_OPERATION_ADD, INetd.LOCAL_NET_ID, iface);
+
+ for (RouteInfo route : routes) {
+ if (!route.isDefaultRoute()) {
+ modifyRoute(MODIFY_OPERATION_ADD, INetd.LOCAL_NET_ID, route);
+ }
+ }
+
+ // IPv6 link local should be activated always.
+ modifyRoute(MODIFY_OPERATION_ADD, INetd.LOCAL_NET_ID,
+ new RouteInfo(new IpPrefix("fe80::/64"), null, iface));
+ }
+
+ /**
+ * Remove iface from local network.
+ */
+ public void removeInterfaceFromLocalNetwork(String iface) {
+ modifyInterfaceInNetwork(MODIFY_OPERATION_REMOVE, INetd.LOCAL_NET_ID, iface);
+ }
+
+ /**
+ * Clear iface addresses.
+ */
+ public void clearInterfaceAddresses(String iface) {
+ try {
+ mNetdService.interfaceClearAddrs(iface);
+ } catch (RemoteException | ServiceSpecificException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ /**
+ * Enable IPv6 on iface.
+ */
+ public void enableIpv6(String iface) {
+ try {
+ mNetdService.interfaceSetEnableIPv6(iface, true);
+ } catch (RemoteException | ServiceSpecificException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ /**
+ * Disable IPv6 on iface.
+ */
+ public void disableIpv6(String iface) {
+ try {
+ mNetdService.interfaceSetEnableIPv6(iface, false);
+ } catch (RemoteException | ServiceSpecificException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ /**
+ * Convert InterfaceConfiguration to InterfaceConfigurationParcel with given ifname.
+ */
+ private static InterfaceConfigurationParcel toStableParcel(InterfaceConfiguration cfg,
+ String iface) {
+ InterfaceConfigurationParcel cfgParcel = new InterfaceConfigurationParcel();
+ cfgParcel.ifName = iface;
+ String hwAddr = cfg.getHardwareAddress();
+ if (!TextUtils.isEmpty(hwAddr)) {
+ cfgParcel.hwAddr = hwAddr;
+ } else {
+ cfgParcel.hwAddr = "";
+ }
+ cfgParcel.ipv4Addr = cfg.getLinkAddress().getAddress().getHostAddress();
+ cfgParcel.prefixLength = cfg.getLinkAddress().getPrefixLength();
+ ArrayList<String> flags = new ArrayList<>();
+ for (String flag : cfg.getFlags()) {
+ flags.add(flag);
+ }
+ cfgParcel.flags = flags.toArray(new String[0]);
+
+ return cfgParcel;
+ }
+
+ /**
+ * Construct InterfaceConfiguration from InterfaceConfigurationParcel.
+ */
+ private static InterfaceConfiguration fromStableParcel(InterfaceConfigurationParcel p) {
+ InterfaceConfiguration cfg = new InterfaceConfiguration();
+ cfg.setHardwareAddress(p.hwAddr);
+
+ final InetAddress addr = NetworkUtils.numericToInetAddress(p.ipv4Addr);
+ cfg.setLinkAddress(new LinkAddress(addr, p.prefixLength));
+ for (String flag : p.flags) {
+ cfg.setFlag(flag);
+ }
+
+ return cfg;
+ }
+
+ private InterfaceConfiguration getInterfaceConfig(String iface) {
+ final InterfaceConfigurationParcel result;
+ try {
+ result = mNetdService.interfaceGetCfg(iface);
+ } catch (RemoteException | ServiceSpecificException e) {
+ throw new IllegalStateException(e);
+ }
+
+ try {
+ final InterfaceConfiguration cfg = fromStableParcel(result);
+ return cfg;
+ } catch (IllegalArgumentException iae) {
+ throw new IllegalStateException("Invalid InterfaceConfigurationParcel", iae);
+ }
+ }
+
+ private void setInterfaceConfig(String iface, InterfaceConfiguration cfg) {
+ LinkAddress linkAddr = cfg.getLinkAddress();
+ if (linkAddr == null || linkAddr.getAddress() == null) {
+ throw new IllegalStateException("Null LinkAddress given");
+ }
+ final InterfaceConfigurationParcel cfgParcel = toStableParcel(cfg, iface);
+
+ try {
+ mNetdService.interfaceSetCfg(cfgParcel);
+ } catch (RemoteException | ServiceSpecificException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ /**
+ * List all tethered interfaces.
+ */
+ public String[] listTetheredInterfaces() {
+ try {
+ return mNetdService.tetherInterfaceList();
+ } catch (RemoteException | ServiceSpecificException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ /**
+ * Register a new netd event observer.
+ */
+ public void registerObserver(NetdEventObserver observer) {
+ mObservers.add(observer);
+ }
+
+ /**
+ * Unregister a new netd event observer.
+ */
+ public void unregisterObserver(NetdEventObserver observer) {
+ mObservers.remove(observer);
+ }
+
+ /**
+ * Set iface down.
+ */
+ public void setInterfaceDown(String iface) {
+ final InterfaceConfiguration ifcg = getInterfaceConfig(iface);
+ ifcg.setInterfaceDown();
+ setInterfaceConfig(iface, ifcg);
+ }
+
+ /**
+ * Set iface up.
+ */
+ public void setInterfaceUp(String iface) {
+ final InterfaceConfiguration ifcg = getInterfaceConfig(iface);
+ ifcg.setInterfaceUp();
+ setInterfaceConfig(iface, ifcg);
+ }
+
+ /**
+ * Returns whether iface is up.
+ */
+ public boolean isInterfaceUp(String iface) {
+ final InterfaceConfiguration ifcg = getInterfaceConfig(iface);
+ return ifcg.isUp();
+ }
+
+ /**
+ * Set iface link address.
+ */
+ public void setInterfaceLinkAddress(String iface, LinkAddress linkAddress) {
+ final InterfaceConfiguration ifcg = getInterfaceConfig(iface);
+ ifcg.setLinkAddress(linkAddress);
+ ifcg.setInterfaceUp();
+ setInterfaceConfig(iface, ifcg);
+ }
+
+ /**
+ * Set iface IPv6 privacy extensions.
+ */
+ public void setInterfaceIpv6PrivacyExtensions(String iface, boolean enable) {
+ try {
+ mNetdService.interfaceSetIPv6PrivacyExtensions(iface, enable);
+ } catch (RemoteException | ServiceSpecificException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ /**
+ * Start tethering.
+ */
+ public void startTethering(String[] dhcpRange) {
+ // an odd number of addrs will fail
+ try {
+ mNetdService.tetherStart(dhcpRange);
+ } catch (RemoteException | ServiceSpecificException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ /**
+ * Stop tethering.
+ */
+ public void stopTethering() {
+ try {
+ mNetdService.tetherStop();
+ } catch (RemoteException | ServiceSpecificException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ /**
+ * Add tethering on iface.
+ */
+ public void tetherInterface(String iface) {
+ try {
+ mNetdService.tetherInterfaceAdd(iface);
+ } catch (RemoteException | ServiceSpecificException e) {
+ throw new IllegalStateException(e);
+ }
+ List<RouteInfo> routes = new ArrayList<>();
+ // The RouteInfo constructor truncates the LinkAddress to a network prefix, thus making it
+ // suitable to use as a route destination.
+ routes.add(new RouteInfo(getInterfaceConfig(iface).getLinkAddress(), null, iface));
+ addInterfaceToLocalNetwork(iface, routes);
+ }
+
+ /**
+ * Remove tethering on iface.
+ */
+ public void untetherInterface(String iface) {
+ try {
+ mNetdService.tetherInterfaceRemove(iface);
+ } catch (RemoteException | ServiceSpecificException e) {
+ throw new IllegalStateException(e);
+ } finally {
+ removeInterfaceFromLocalNetwork(iface);
+ }
+ }
+
+ /**
+ * Returns whether tethering has been started.
+ */
+ public boolean isTetheringStarted() {
+ try {
+ final boolean isEnabled = mNetdService.tetherIsEnabled();
+ return isEnabled;
+ } catch (RemoteException | ServiceSpecificException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+
+ /**
+ * Notify our observers of an interface status change
+ */
+ private void notifyInterfaceStatusChanged(String iface, boolean up) {
+ for (NetdEventObserver observer : mObservers) {
+ observer.interfaceStatusChanged(iface, up);
+ }
+ }
+
+ /**
+ * Notify our observers of an interface link state change
+ * (typically, an Ethernet cable has been plugged-in or unplugged).
+ */
+ private void notifyInterfaceLinkStateChanged(String iface, boolean up) {
+ for (NetdEventObserver observer : mObservers) {
+ observer.interfaceLinkStateChanged(iface, up);
+ }
+ }
+}
+