I want to know how to detect state of WiFi tethering. I've seen an article: Android 2.3 wifi hotspot API But it doesn't work! It returns always WIFI_AP_STATE_DISABLED = 1. It doesn't depend on real state of WiFi tethering.
Using reflection:
WifiManager wifi = (WifiManager) getSystemService(Context.WIFI_SERVICE);
Method[] wmMethods = wifi.getClass().getDeclaredMethods();
for (Method method: wmMethods) {
if (method.getName().equals("isWifiApEnabled")) {
try {
boolean isWifiAPenabled = method.invoke(wifi);
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
As you can see here
In addition to the reflexion, to get the Wifi tethering status update, you can listen to this broadcast Action :
IntentFilter filter = new IntentFilter("android.net.wifi.WIFI_AP_STATE_CHANGED");
To get all tethering option update :
IntentFilter filter = new IntentFilter("android.net.conn.TETHER_STATE_CHANGED");
Those actions are hidden inside the Android source code
First, you need to get WifiManager:
Context context = ...
final WifiManager wifi = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
Then:
public static boolean isSharingWiFi(final WifiManager manager)
{
try
{
final Method method = manager.getClass().getDeclaredMethod("isWifiApEnabled");
method.setAccessible(true); //in the case of visibility change in future APIs
return (Boolean) method.invoke(manager);
}
catch (final Throwable ignored)
{
}
return false;
}
Also you need to request a permission in AndroidManifest.xml:
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
Here is the Xamarin C# version if anyone is looking:
static Method isWifiApEnabledMethod;
public static bool IsWifiApEnabled ()
{
var wifiManager = WifiManager.FromContext (Application.Context);
if (isWifiApEnabledMethod == null)
{
try
{
isWifiApEnabledMethod = wifiManager.Class.GetDeclaredMethod ("isWifiApEnabled");
isWifiApEnabledMethod.Accessible = true; //in the case of visibility change in future APIs
}
catch (NoSuchMethodException e)
{
Debug.WriteLine ("Can't get method by reflection" + e);
}
catch (System.Exception ex)
{
Debug.WriteLine ("Can't get method by reflection" + ex);
}
}
if (isWifiApEnabledMethod != null)
{
try
{
return (bool)isWifiApEnabledMethod.Invoke (wifiManager);
}
catch (System.Exception ex)
{
Debug.WriteLine ("Can't invoke by reflection" + ex);
}
}
return false;
}
(without using reflection since they say google is restricting it)
I'm writting this answer 10 years later. also I don't know if this can be considered a good aproach or not but I first get the Wlan network interface IPs
and if there is no address I assume that it tethering isn't enabled. if there is an address, I check using the connectivity manger whether WI-FI is connected to a network or not. if there is an IP for the Wlan network interface but it isn't connected to a network, I assume tethering is enabled.
you probably would need to add this line to your manifest file
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
code to get the ip of an inteface (this only gets the IPv4, you can modify it to get the IPv6 or both if you want)
// method used to retrieve Wlan ip addresses IPv4 of the device.
public static String IpAddresses() throws NoAddressFoundException, SocketException {
Enumeration<NetworkInterface> Nics = NetworkInterface.getNetworkInterfaces();
while (Nics.hasMoreElements()) {
NetworkInterface NIC = Nics.nextElement();
if (NIC.isUp() && !NIC.isLoopback() && NIC.getName().contains("wlan")) {
Enumeration<InetAddress> Addresses = NIC.getInetAddresses();
while (Addresses.hasMoreElements()) {
InetAddress WlanAddress = Addresses.nextElement();
if (WlanAddress instanceof Inet4Address)
return WlanAddress.getHostAddress();
}
}
}
throw new NoAddressFoundException("No suitable wifi address found");
}
then if there is an address i check if wifi is connected by this method:
//method to check if the device is connected to a Wi-Fi network; it doesn't matter if network has access to internet
public static boolean isWifiConnected(Context context) {
ConnectivityManager ConMan = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo WifiInfo = ConMan.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
return WifiInfo.isConnected();
}
NOTE: the "NoAddressFoundException" is a custom exception in my app if anyone is wondering. it won't exist in your case.
Reflection is a poor way to achieve this.
We can inspect the DhcpInfo to determine if the device is allocating addresses (mobile hotspot) or is being allocated by another DHCP server.
Here is a kotlin function that will determine if a device is a mobile hotspot, it has not been widely tested so YMMV.
fun isMobileHotspot(manager: WifiManager): Boolean {
val info = manager.dhcpInfo
return (
info.ipAddress == 0
&& info.netmask == 0
&& info.gateway == 0
&& info.serverAddress == 16885952) // 192.168.1.1
}
Related
Is there any way besides the standard ConnectivityManager-API to modify wifi state in android q? I've just read google removed the api in android 10. Im willing to give the app android device administrator status, grant all permissions with adb, etc as I wont publish the app and will only use it for myself.
Your app must be a device owner as a variant to use wifiManager.setWifiEnabled(false) method that is deprecated started from Q.
Deprecation Exemptions:
Device Owner (DO), Profile Owner (PO) and system apps.
WifiManager
You can use the following code to disable wifi :
try {
WifiManager wifiManager = (WifiManager) context.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
return wifiManager.setWifiEnabled(false);
} catch (Exception ex) {
ex.printStackTrace();
return false;
}
to disconnect wifi :
WifiManager wifiManager = (WifiManager)context.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
wifiManager.disconnect();
and the following code to forget a particular wifi network :
try {
WifiManager wifiManager = (WifiManager) context.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
List wifiNetworks = wifiManager.getConfiguredNetworks();
for (Object wifiConf : wifiNetworks) {
if (((WifiConfiguration) wifiConf).SSID.equalsIgnoreCase(SSID)) {
return wifiManager.removeNetwork(wifiManager.getConnectionInfo().getNetworkId()) && wifiManager.saveConfiguration();
}
}
} catch (Exception ex) {
ex.printStackTrace();
}
Basically, what I need is check if my Wifi connection has Internet access. The most effective way I know is with sock.connect() but I need to be sure that the connection will be done through the Wifi network and this is my main issue,
I was searching for a few days about this and there is not a good response to this.
There are a lot of solutions like How do I see if Wi-Fi is connected on Android? but they only check if the device is connected to a router. I need to know if the router as internet access
My best approximation was this:
Socket sock = new Socket();
ConnectivityManager
cm = (ConnectivityManager) mContext.getApplicationContext()
.getSystemService(Context.CONNECTIVITY_SERVICE);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
Network net = cm.getActiveNetwork();
net.bindSocket(sock);
}
sock.connect(new InetSocketAddress("8.8.8.8", 53), 1500);
sock.close();
But this has some limitations. The biggest limitation is that only works for API >= 23.
Also, if I am in China I think that hostname "8.8.8.8" will not work, right?
And finally, cm.getActiveNetwork() will only be the WIFI network if my device is connected to a wifi network, and this is not totally true because it is possible to modify the default active network.
What I need to know is:
Is there any working alternative for API >= 16?
Is there a good hostname that will work fine in China?
Any help will be appreciated,
Thanks in advance!
Yes you have to check with a remote server in order to be sure.
A common way would be like this:
NetworkInfo activeNetwork = connectivityManager.getActiveNetworkInfo();
boolean isConnected = activeNetwork != null && activeNetwork.isConnectedOrConnecting();
if (isConnected) {
try {
InetAddress ipAddr = InetAddress.getByName("google.com");
if (ipAddr.isReachable(5000)) {
// Internet access OK!
}
} catch (Exception e) {
// Error handling...
}
}
Prefer domain names when calling getByName rather than IPs (https://docs.oracle.com/javase/7/docs/api/java/net/InetAddress.html#getByName(java.lang.String))
If you want to avoid the connectivity manager you can register a BroadcastReceiver for WifiManager.NETWORK_STATE_CHANGED_ACTION events and you will know if you are connected to a WiFi (the current state is received almost immediately).
As regards the region issue I am out of ideas, maybe use NTP servers instead of google (much more innocent servers) or try Baidu!?
Finally, I came to a solution:
public interface Consumer {
void accept(Boolean internet);
}
class InternetCheck extends AsyncTask<Void, Void, Boolean> {
private Consumer mConsumer;
public InternetCheck(Consumer consumer) {
mConsumer = consumer;
execute();
}
#Override
protected Boolean doInBackground(Void... voids) {
Socket socket = null;
try {
WifiManager wifiManager = (WifiManager) mContext.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
if (wifiManager != null) {
socket = new Socket();
socket.setKeepAlive(false);
String localIpAddress = getIpAddress(wifiManager);
socket.bind(new InetSocketAddress(localIpAddress, 0));
socket.connect(new InetSocketAddress("8.8.8.8", 53), 1500);
return true;
}
return false;
} catch (IOException e) {
//unbind();
return false;
}finally {
if(socket != null && !socket.isClosed()) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
#Override
protected void onPostExecute(Boolean internet) {
mConsumer.accept(internet);
}
}
public static String getIpAddress(WifiManager wifiManager) {
WifiInfo wifiInfo = wifiManager.getConnectionInfo();
int ipAddress = wifiInfo.getIpAddress();
return String.format(Locale.getDefault(), "%d.%d.%d.%d", (ipAddress & 0xff), (ipAddress >> 8 & 0xff),
(ipAddress >> 16 & 0xff), (ipAddress >> 24 & 0xff));
}
I came to a solution after saw this question. With this, I obtained the IP address of my wifi connection and with this, I was able to bind the socket (socket.bind(...)) to the wifi connection and be check if my router had internet access.
I hope this solution helps somebody in the future :)
I have update my mobile to Android Lollipop, before updating to Lollipop it works fine. Now I am facing problem with network interface.
if (isWifiConnected()) {
Log.d(TAG,"Wifi is connected");
mNetIf = Utils.getActiveNetworkInterface();
String name = mNetIf.getName();
Log.d(TAG, "network interface in constructor" + NetworkInterface.getByName(name));
//do some multicast Operations.
}
If the WiFi is connected I should do some multicast operation in WiFi.
iswifiConnected method
public boolean isWifiConnected(){
ConnectivityManager connManager = (ConnectivityManager)mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo mWifi = connManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
if (mWifi.isConnected()) {
return true;
}
return false;
}
Utils.getActiveNetworkInterface
public static NetworkInterface getActiveNetworkInterface() {
Enumeration<NetworkInterface> interfaces = null;
try {
interfaces = NetworkInterface.getNetworkInterfaces();
} catch (SocketException e) {
return null;
}
while (interfaces.hasMoreElements()) {
NetworkInterface iface = interfaces.nextElement();
Enumeration<InetAddress> inetAddresses = iface.getInetAddresses();
/* Check if we have a non-local address. If so, this is the active
* interface.
*
* This isn't a perfect heuristic: I have devices which this will
* still detect the wrong interface on, but it will handle the
* common cases of wifi-only and Ethernet-only.
*/
while (inetAddresses.hasMoreElements()) {
InetAddress addr = inetAddresses.nextElement();
if (!(addr.isLoopbackAddress() || addr.isLinkLocalAddress())) {
return iface;
}
}
}
return null;
}
Log
Wifi is connected
network interface in constructor**[rmnet0][3]t** [/fe80::32e3:daf0:ba51:f971%rmnet0%3][/27.57.104.11]//3g network interface
I am wondering how the app got 3g interface. It should get wlan interface, it work in all other mobile. Is it a bug?
Permissions:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
You are using the ConnectivityManger but, to use the WiFi network in Android, the best choice is to use the WifiManager: it has many features dedicated to Wifi. In particular, if you want to get a NetworkInterface object referencing the WiFi Interface, you can use the following method:
public static NetworkInterface getActiveWifiInterface(Context context) throws SocketException, UnknownHostException {
WifiManager wifiManager = (WifiManager)context.getSystemService(Context.WIFI_SERVICE);
//Return dynamic information about the current Wi-Fi connection, if any is active.
WifiInfo wifiInfo = wifiManager.getConnectionInfo();
if(wifiInfo == null) return null;
InetAddress address = intToInet(wifiInfo.getIpAddress());
return NetworkInterface.getByInetAddress(address);
}
public static byte byteOfInt(int value, int which) {
int shift = which * 8;
return (byte)(value >> shift);
}
public static InetAddress intToInet(int value) {
byte[] bytes = new byte[4];
for(int i = 0; i<4; i++) {
bytes[i] = byteOfInt(value, i);
}
try {
return InetAddress.getByAddress(bytes);
} catch (UnknownHostException e) {
// This only happens if the byte array has a bad length
return null;
}
}
I think the problem is that getInetAddresses() returns a list of interfaces, and getActiveNetworkInterface is only returning the first one no matter what.
And so the interface you are getting depends on the order of the list which getInetAddresses() returns.
That being said, one of the solutions could be: look at the up interface, using isUp().
http://developer.android.com/reference/java/net/NetworkInterface.html#isUp()
Android would turn off the cellular connection to save power when connected to wifi networks, so by looking at only the UP interface, you should able to pin point the WiFi interface.
I have a small issue regarding Ethernet.
My three questions are:
Can we programmatically Turn-On/Off Ethernet?
Can we programmatically Enable/Disable Ethernet?
Can we programmatically Connect Ethernet?
The above Questions are done with the Wifi. Like
We can programmatically Turn-On/Off Wifi.
We can programmatically Enable/Disable Wifi.
We can programmatically Connect Wifi using WifiManager.
Does android provides any EthernetManager like as WifiManager to handle Ethernet?
Or, if this doesn't seem feasible, then my original requirement is:
The first thing I am going to clear is "DEVICE IS ROOTED" .
Can I manipulate the Settings (Default)? Like I don't want any other option in the Settings.apk other than WIFI and Ethernet. It should show only Wifi and Ethernet. That's it. Can I disable all the options from the Settings or Can I remove all the other options from the Settings?
The solution I will present here is a hack using reflection and does only work on a rooted android system.
Your device might have the popular android.net.ethernet package. In an Activity, try
Object emInstance = getSystemService("ethernet");
It returns an valid instance of the EthernetManager or null. Null means you are out of luck.
An additional requirement might be depending on your device: Ethernet and Wifi might only work exclusively. You might need to disable Wifi to enable Ethernet and vice versa.
To enable Ethernet by reflection use your instance of the EthernetManager.
The method you want to invoke is setEthEnabled(boolean enabled)
Class<?> emClass = null;
try {
emClass = Class.forName("android.net.ethernet.EthernetManager");
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Object emInstance = getSystemService("ethernet");
Method methodSetEthEnabled = null;
try {
methodSetEthEnabled = emClass.getMethod("setEthEnabled", Boolean.TYPE);
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
methodSetEthEnabled.setAccessible(true);
try {
// new Boolean(true) to enable, new Boolean(false) to disable
methodSetEthEnabled.invoke(emInstance, new Boolean(false));
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Your application manifest needs these permissions
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
The permission WRITE_SECURE_SETTINGS can only be acquired by system apps. The app does not need to be signed by a system key. It can be any valid sign (like the regular Android App Export function). Use busybox to remount the system partition for write access and move your apk into the /system/app folder. Reboot the device and it should work.
Can we programmatically Connect Ethernet ?
There is no Access Point to connect you like with Wifi. You either configure it for DHCP or provide static values. This can of course also be done via reflection.
You will need the class EthernetDevInfo for that.
The actual implementation of the EthernetManager and EthernetDevInfo might slightly differ between Android versions and devices as it doesn't have to conform to a public api (yet) and might even be a custom version.
To get a list of getters and setters you can use a Introspector or reflection in general.
Ok here are some methods i made for manipulating with the ETHERNET INTERFACE (eth0).
1) A method for checking if an ethernet interface exists
public static boolean doesEthExist() {
List<String> list = getListOfNetworkInterfaces();
return list.contains("eth0");
}
public static List<String> getListOfNetworkInterfaces() {
List<String> list = new ArrayList<String>();
Enumeration<NetworkInterface> nets;
try {
nets = NetworkInterface.getNetworkInterfaces();
} catch (SocketException e) {
e.printStackTrace();
return null;
}
for (NetworkInterface netint : Collections.list(nets)) {
list.add(netint.getName());
}
return list;
}
2) A method for checking if the ETHERNET is enabled or ON
public static boolean isEthOn() {
try {
String line;
boolean r = false;
Process p = Runtime.getRuntime().exec("netcfg");
BufferedReader input = new BufferedReader (new InputStreamReader(p.getInputStream()));
while ((line = input.readLine()) != null) {
if(line.contains("eth0")){
if(line.contains("UP")){
r=true;
}
else{
r=false;
}
}
}
input.close();
Log.e("OLE","isEthOn: "+r);
return r;
} catch (IOException e) {
Log.e("OLE","Runtime Error: "+e.getMessage());
e.printStackTrace();
return false;
}
}
3) A method for enabling or disabling the Ethernet depending on the state in which it is
public static void turnEthOnOrOff() {
try {
if(isEthOn()){
Runtime.getRuntime().exec("ifconfig eth0 down");
}
else{
Runtime.getRuntime().exec("ifconfig eth0 up");
}
} catch (IOException e) {
Log.e("OLE","Runtime Error: "+e.getMessage());
e.printStackTrace();
}
}
4) A method for connecting via ethernet depending on the chosen type (dhcp/static)
private boolean connectToStaticSettingsViaIfconfig(StaticConnectionSettings scs) {
try {
if(typeChosen.equalsIgnoreCase("dhcp")){
Runtime.getRuntime().exec("ifconfig eth0 dhcp start");
}
else{
Runtime.getRuntime().exec("ifconfig eth0 "+scs.getIp()+" netmask "+scs.getNetmask()+" gw "+scs.getGateway());
}
} catch (IOException e) {
Log.e("OLE","Runtime Error: "+e.getMessage());
e.printStackTrace();
return false;
}
return true;
}
There is one more class which i created for storing all the eth values needed. This class is than initialized with the values the user inserts.
public class StaticConnectionSettings {
private String ip, netmask, dns, mac, gateway, type;
//Getters and Setters
}
This is it ... I will test it shortly... This code lacks a test phase (ping). And maybe it needs setting of DNS. But this can be done easily. I have not included it because i think on our device it will work also without the DNS setting.
It works for Android 6.0.1
Class<?> ethernetManagerClass = Class.forName("android.net.ethernet.EthernetManager");
Method methodGetInstance = ethernetManagerClass.getMethod("getInstance");
Object ethernetManagerObject = methodGetInstance.invoke(ethernetManagerClass);
Method methodSetEthEnabled = ethernetManagerClass.getMethod("setEthernetEnabled", Boolean.TYPE);
methodSetEthEnabled.invoke(ethernetManagerObject, isEnabled);
Three Answeres to your above questions:
Yes. You could try using ifconfig eth0 down ; ifconfig eth0 up. But i have not tested it by myself yet.
Yes, but you do not have to. Android does the switching for you. If you connect to WiFi, Ethernet disables. If you are already connected to WiFi and you plug your ethernet cable into the device; you need only to disable WiFi (which you know how to) and android switches automatically to ethernet.
Not so easy as you may think. I have the same problem and until now i have found only one solution which i have not yet tested. Since android runs on the linux kernel, we can use ifconfig in order to manipulate the ethernet connection.
An explanation is hidden here:
http://elinux.org/images/9/98/Dive_Into_Android_Networking-_Adding_Ethernet_Connectivity.pdf
And the youtube video of this lecture
http://www.youtube.com/watch?v=LwI2NBq7BWM
And a reference on how to use ifconfig for android
Android ethernet configure IP using dhcp
So if you come to a possible solution, please share it!! If i will do it before you i will certenly.
I'm turning portable wifi hotspot ON by following code:
private void createWifiAccessPoint() {
WifiManager wifiManager = (WifiManager)getBaseContext().getSystemService(Context.WIFI_SERVICE);
if(wifiManager.isWifiEnabled())
{
wifiManager.setWifiEnabled(false);
}
Method[] wmMethods = wifiManager.getClass().getDeclaredMethods(); //Get all declared methods in WifiManager class
boolean methodFound=false;
for(Method method: wmMethods){
if(method.getName().equals("setWifiApEnabled")){
methodFound=true;
WifiConfiguration netConfig = new WifiConfiguration();
netConfig.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);
netConfig.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
netConfig.allowedProtocols.set(WifiConfiguration.Protocol.WPA);
netConfig.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
netConfig.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
netConfig.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
netConfig.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
netConfig.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
try {
boolean apstatus=(Boolean) method.invoke(wifiManager, netConfig,true);
//statusView.setText("Creating a Wi-Fi Network \""+netConfig.SSID+"\"");
for (Method isWifiApEnabledmethod: wmMethods)
{
if(isWifiApEnabledmethod.getName().equals("isWifiApEnabled")){
while(!(Boolean)isWifiApEnabledmethod.invoke(wifiManager)){
};
for(Method method1: wmMethods){
if(method1.getName().equals("getWifiApState")){
int apstate;
apstate=(Integer)method1.invoke(wifiManager);
// netConfig=(WifiConfiguration)method1.invoke(wifi);
//statusView.append("\nSSID:"+netConfig.SSID+"\nPassword:"+netConfig.preSharedKey+"\n");
}
}
}
}
if(apstatus)
{
System.out.println("SUCCESSdddd");
//statusView.append("\nAccess Point Created!");
//finish();
//Intent searchSensorsIntent = new Intent(this,SearchSensors.class);
//startActivity(searchSensorsIntent);
}else
{
System.out.println("FAILED");
//statusView.append("\nAccess Point Creation failed!");
}
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
if(!methodFound){
//statusView.setText("Your phone's API does not contain setWifiApEnabled method to configure an access point");
}
}
It works for me....... Hotspot turns on...... But there are also advanced settings by clicking 'menu' button.... And here is a problem... DHCP becomes disabled in LanSettings and Power Mode is only 5 minutes working on.... I want DHCP tto be ENABLED and PowerMode - "always on"...How can I resolve it?
You might have to look through the Android source code to find the answer to this. With your code is a device able to connect and get an IP address? If that is the case then DHCP for the AP is working.
Personally I don't even have a DHCP enabled or disabled option or a PowerMode on ICS.