[Xperia Arc General] thotypous:
Regulatory domain (Wi-Fi channels 12 and 13) fix for the factory (default) ROM

I managed to fix the regulatory domain in order to be able to use the wireless channels 12 and 13 in the factory ROM. I only tested this procedure in the Xperia Pro (MK16a) and using the factory GingerBread ROM, although the procedure should be similar for other Xperia models and for the ICS ROM.

Well, it still needs rooting, but for those worried about the warranty it should be better than unlocking the bootloader or installing another ROMs, because you can root your phone, apply the fix, then unroot it, and nobody will ever know the phone was once rooted unless they do a deep forensic analysis.

How the regulatory domain works in Xperia devices

Sony added a class named "com/android/server/WifiService$RegulatoryDomain" which isn't part of standard AOSP. This class checks in which country you currently are based on the current MCC (Mobile Country Code), extracted from the first 3 digits of the current PLMN. Then there is a list of MCCs of countries on which 13 Wi-Fi channels are allowed. If your MCC is on the list, it enables 13 channels, otherwise it only enables 11 channels.

If your current MCC is not on the list, your wifi_num_allowed_channels setting has no effect. It is always reseted to 11.

Note that this is an "Android framework-level lock", not a "Linux-level or driver-level lock", because if you try to run iwlist (you can build yours from this svn repo) it shows channel 12 and 13 Wi-Fi networks even without any modification to the factory ROM.

The problem

The problem is that not all countries which allow 13 Wi-Fi channels are listed in the "WifiService$RegulatoryDomain" class. Apparently, there are typo errors in some MCCs.

For example, Brazil is MCC 724, but the class lists MCC 742, which according to this listing is a non-existent MCC. So it's apparently a typo error. They typed 742 instead of 724.

Fixing it

First, root your device. I used FlashTool for this.

Then, copy /system/framework/services.jar from your device to your computer using adb. Then unpack it (unzip or 7zip or whatever), use baksmali for disassembling classes.dex, and open "com/android/server/WifiService$RegulatoryDomain.smali" in a text editor.

Look for something like:

const/16 v7, 0x24

const-string v8, "742"

aput-object v8, v6, v7

iput-object v6, p0, Lcom/android/server/WifiService$RegulatoryDomain;->mHighChannelsMccs:[Ljava/lang/String;

This is where the 13-channels-allowed MCC list is being built. The "742" is the apparently non-existent MCC. Just replace it by the MCC of your country. Look at this listing or look at the first 3 digits of the PLMN:

$ adb logcat | grep PLMN
E/WifiService( 241): Could not get PLMN!
E/WifiService( 241): Could not get PLMN!
E/WifiService( 241): Could not get PLMN!
I/WifiService( 241): PLMN = 72410
I/WifiService( 241): PLMN = 72410

In my case I just replaced "742" by "724".

Then use smali for assembling the code back to the classes.dex file, and repack the services.jar file using jar, zip or another tool.

Finally, copy your modified services.jar to your device's /system/framework/services.jar using adb, and reboot your phone. Now everything should work.

About the attached file

My modified services.jar is attached for reference. Remember it is for the Xperia Pro factory GB ROM. If you use ICS or if you have another Xperia device, you need to baksmali/modify/smali your own jar file as described above.