[RK3288][RK3399] 打开支持2.4G和5G热点的开关

最近在rk3288 android5.1/7.1和rk3399 android7.1上调试了ap6256芯片(该芯片支持5G wifi),但是我打开AP热点时候只能生成2.4G频段的AP。在“设置WLAN热点”里面有一个“选择AP频段”的选项(android5.1没有该开关,这个也是后来我调试5.1的时候才发现的,之后我已经解决了),但是该选项里面只有一个2.4GHz频段的选项,并没有5G频段的选项。之前我在https://blog.csdn.net/Mrdeath/article/details/103030362里有写怎么打开5G AP,但是该文章的方法是写死的,也就是说只能打开5G热点,没办法2.4G和5G之间切换。不过在设置里面既然有“2.4G频段”的选项,那一定也有5G的选项,其中5G选项应该是被系统隐藏了,因此展开调查,来打开5G选项开关,并能成功设置5G热点。

1.在packages/apps/Settings/目录下搜关键字"2.4 GHz 频段",结果:

packages/apps/Settings/res/values-zh-rCN/strings.xml:    "2.4 GHz 频段"

2.提取到string name :wifi_ap_choose_2G,继续在packages/apps/Settings/目录下搜:

packages/apps/Settings/res/values/arrays.xml:        @string/wifi_ap_choose_2G

3.进入array.xml查看该xml



 
     @string/wifi_ap_choose_2G
     @string/wifi_ap_choose_5G
 

 
     @string/wifi_ap_choose_2G
 

看到果然是有5G选项对应的字符串:wifi_ap_choose_5G

4.提取wifi_ap_band_config_full字符,在packages/apps/Settings目录下继续搜索:

packages/apps/Settings/src/com/android/settings/wifi/WifiApDialog.java:                    R.array.wifi_ap_band_config_full, android.R.layout.simple_spinner_item);

5.进到WifiApDialog.java下,查看:

if (!mWifiManager.isDualBandSupported() || countryCode == null) {
    //If no country code, 5GHz AP is forbidden
    Log.i(TAG,(!mWifiManager.isDualBandSupported() ? "Device do not support 5GHz " :"")
            + (countryCode == null ? " NO country code" :"") +  " forbid 5GHz");
    channelAdapter = ArrayAdapter.createFromResource(mContext,
            R.array.wifi_ap_band_config_2G_only, android.R.layout.simple_spinner_item);
    mWifiConfig.apBand = 0;
} else {
    channelAdapter = ArrayAdapter.createFromResource(mContext,
            R.array.wifi_ap_band_config_full, android.R.layout.simple_spinner_item);
}

这里很明显了,有一个if判断:if (!mWifiManager.isDualBandSupported() || countryCode == null)

也就是mWifiManager.isDualBandSupported() !=null 并且countryCode != null,才能进入wifi_ap_band_config_full模式,

countryCode字面意思就是要有国家代码,在我们中国国内5G信道只允许使用149以上的信道,因此没设置国家是无法使用5G热点的。

国家代码先放一边,先来调查isDualBandSupported的作用:

6.在frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiServiceImpl.java目录下有对isDualBandSupported方法的定义:

public boolean isDualBandSupported() {
    //TODO: Should move towards adding a driver API that checks at runtime
    return mContext.getResources().getBoolean(
            com.android.internal.R.bool.config_wifi_dual_band_support);
}

从代码中可以理解到,isDualBandSupported方法返回值是个bool类型值,它返回的是config_wifi_dual_band_support所对应的值,因此我们只要去确认config_wifi_dual_band_support是true还是false就可以了,不过现在看来该值应该是被设置成了false,下面我们继续去查找该值真正被设置成了什么:

7.在frameworks/base/core/res/res/values/config.xml目录下,有对config_wifi_dual_band_support值的设置,该值果然是被设置成了false,现在把它改为true。


true

这里设置成true后,isDualBandSupported应该已经是为true了,要想打开5G开关,还需要设置国家代码,继续调查国家代码是如何设置的:

8.我们回到packages/apps/Settings/src/com/android/settings/wifi/WifiApDialog.java目录,查看countryCode是怎么设置的

String countryCode = mWifiManager.getCountryCode();

在WifiApDialog.java文件里面有对countryCode 的提取:String countryCode = mWifiManager.getCountryCode(),既然有get,那一定有地方set,我们就去找set地方,然而set国家代码是根据phoneNumber去设置的,而我的板子压根就没插SIM卡,我的AP是以太网转AP,因此也不用sim卡,因此,我们只能写死一个中国的countryCode ,在packages/apps/Settings/src/com/android/settings/wifi/WifiApDialog.java里把String countryCode = "CN"; 写死

 ArrayAdapter  channelAdapter;
 //String countryCode = mWifiManager.getCountryCode();
 String countryCode = "CN"; // 写死为中国国家代码

最终编译烧写完成,打开WLAN热点开关发现,isDualBandSupported返回值还是为false,失败!

于是我尝试把WifiApDialog.java文件里的if判断改掉,改成 只判断国家代码:

if (countryCode == null){
//if (!mWifiManager.isDualBandSupported() || countryCode == null) {
    //If no country code, 5GHz AP is forbidden
    Log.i(TAG,(!mWifiManager.isDualBandSupported() ? "Device do not support 5GHz " :"")
            + (countryCode == null ? " NO country code" :"") +  " forbid 5GHz");
    channelAdapter = ArrayAdapter.createFromResource(mContext,
            R.array.wifi_ap_band_config_2G_only, android.R.layout.simple_spinner_item);
    mWifiConfig.apBand = 0;
} else {
    channelAdapter = ArrayAdapter.createFromResource(mContext,
            R.array.wifi_ap_band_config_full, android.R.layout.simple_spinner_item);
}

再次编译,烧写测试。在设置栏里面出现了“5G 频段”的选项,但是5Gwifi没法放热点,一设置5G热点就会报错,估计是因为是没有设置5G信道导致的。那就继续往下调查

9.在网络上搜索rk3288 5G AP相关资料后,无意中发现一份《使能5G AP分析》的文档,看了这份文档后发现,它就是去添加5G的信道,刚好符合我的需求,上面所设置的内容加上这篇文章中所写的内容,两者结合应该是可以实现2.4G和5G 热点的切换。

添加5G的补丁:frameworks/opt/net/wifi/service/java/com/android/server/wifi/util/ApConfigUtil.java

diff --git a/service/java/com/android/server/wifi/util/ApConfigUtil.java b/service/java/com/android/server/wifi/util/ApConfigUtil.java
index 0e12f06..bbf4a11 100644
--- a/service/java/com/android/server/wifi/util/ApConfigUtil.java
+++ b/service/java/com/android/server/wifi/util/ApConfigUtil.java
@@ -33,6 +33,7 @@ public class ApConfigUtil {
 
     public static final int DEFAULT_AP_BAND = WifiConfiguration.AP_BAND_2GHZ;
     public static final int DEFAULT_AP_CHANNEL = 6;
+	public static final int DEFAULT_AP_CHANNEL_5GHz = 153;
 
     /* Return code for updateConfiguration. */
     public static final int SUCCESS = 0;
@@ -115,16 +116,25 @@ public class ApConfigUtil {
                                             WifiConfiguration config) {
         /* Use default band and channel for device without HAL. */
         if (!wifiNative.isHalStarted()) {
-            config.apBand = DEFAULT_AP_BAND;
-            config.apChannel = DEFAULT_AP_CHANNEL;
-            return SUCCESS;
+            //add by louhn
+			if (WifiConfiguration.AP_BAND_2GHZ == config.apBand)
+				config.apChannel = DEFAULT_AP_CHANNEL;
+			else if (WifiConfiguration.AP_BAND_5GHZ == config.apBand)
+				config.apChannel = DEFAULT_AP_CHANNEL_5GHz;
+			else {
+				config.apBand = DEFAULT_AP_BAND;
+				config.apChannel = DEFAULT_AP_CHANNEL;
+			}
+			//add end
+			return SUCCESS;
         }
 
         /* Country code is mandatory for 5GHz band. */
         if (config.apBand == WifiConfiguration.AP_BAND_5GHZ
                 && countryCode == null) {
-            Log.e(TAG, "5GHz band is not allowed without country code");
-            return ERROR_GENERIC;
+            //Log.e(TAG, "5GHz band is not allowed without country code");
+            Log.e(TAG, "5GHz band is not allowed without country code, use channel:153 for 5GHz AP");
+			//return ERROR_GENERIC;
         }
 
         /* Select a channel if it is not specified. */

打完以上补丁后,5G AP终于能够成功生成,并且2.4G跟5G能够双切换了。

 

最终附上我这次修改的所有补丁,补丁是在rk3399_android7.1上生成的,rk3288也一样参考修改

diff --git a/src/com/android/settings/wifi/WifiApDialog.java b/src/com/android/settings/wifi/WifiApDialog.java
index 1316a49..41c8f45 100644
--- a/src/com/android/settings/wifi/WifiApDialog.java
+++ b/src/com/android/settings/wifi/WifiApDialog.java
@@ -134,8 +134,18 @@ public class WifiApDialog extends AlertDialog implements View.OnClickListener,
         mPassword = (EditText) mView.findViewById(R.id.password);
 
         ArrayAdapter  channelAdapter;
-        String countryCode = mWifiManager.getCountryCode();
-        if (!mWifiManager.isDualBandSupported() || countryCode == null) {
+        //String countryCode = mWifiManager.getCountryCode();
+        String countryCode = "CN";
+		if( countryCode == null)
+		{
+			Log.i("LOUHN","countryCode == null");
+		}
+		if(!mWifiManager.isDualBandSupported())
+		{
+			Log.i("LOUHN","mWifiManager.isDualBandSupported()=null");
+		}
+		if (countryCode == null){
+		//if (!mWifiManager.isDualBandSupported() || countryCode == null) {
             //If no country code, 5GHz AP is forbidden
             Log.i(TAG,(!mWifiManager.isDualBandSupported() ? "Device do not support 5GHz " :"") 
                     + (countryCode == null ? " NO country code" :"") +  " forbid 5GHz");

diff --git a/service/java/com/android/server/wifi/util/ApConfigUtil.java b/service/java/com/android/server/wifi/util/ApConfigUtil.java
index 0e12f06..bbf4a11 100644
--- a/service/java/com/android/server/wifi/util/ApConfigUtil.java
+++ b/service/java/com/android/server/wifi/util/ApConfigUtil.java
@@ -33,6 +33,7 @@ public class ApConfigUtil {
 
     public static final int DEFAULT_AP_BAND = WifiConfiguration.AP_BAND_2GHZ;
     public static final int DEFAULT_AP_CHANNEL = 6;
+	public static final int DEFAULT_AP_CHANNEL_5GHz = 153;
 
     /* Return code for updateConfiguration. */
     public static final int SUCCESS = 0;
@@ -115,16 +116,25 @@ public class ApConfigUtil {
                                             WifiConfiguration config) {
         /* Use default band and channel for device without HAL. */
         if (!wifiNative.isHalStarted()) {
-            config.apBand = DEFAULT_AP_BAND;
-            config.apChannel = DEFAULT_AP_CHANNEL;
-            return SUCCESS;
+            //add by louhn
+			if (WifiConfiguration.AP_BAND_2GHZ == config.apBand)
+				config.apChannel = DEFAULT_AP_CHANNEL;
+			else if (WifiConfiguration.AP_BAND_5GHZ == config.apBand)
+				config.apChannel = DEFAULT_AP_CHANNEL_5GHz;
+			else {
+				config.apBand = DEFAULT_AP_BAND;
+				config.apChannel = DEFAULT_AP_CHANNEL;
+			}
+			//add end
+			return SUCCESS;
         }
 
         /* Country code is mandatory for 5GHz band. */
         if (config.apBand == WifiConfiguration.AP_BAND_5GHZ
                 && countryCode == null) {
-            Log.e(TAG, "5GHz band is not allowed without country code");
-            return ERROR_GENERIC;
+            //Log.e(TAG, "5GHz band is not allowed without country code");
+            Log.e(TAG, "5GHz band is not allowed without country code, use channel:153 for 5GHz AP");
+			//return ERROR_GENERIC;
         }
 
         /* Select a channel if it is not specified. */

以上内容是我昨天做rk3288 android7.1和rk3399 android的内容,今天我准备以同样方式在rk3288 android5.1上添加5G AP选择开关的时候发现,rk3288根本就没有预留2.4G和5G AP的选择开关,也就是说,我必须自己写一个开关!好吧,前面那一句“补丁是在rk3399_android7.1上生成的,rk3288也一样参考修改”的话我收回,我们现在就去解决,如何在rk3288android5.1上添加ap频段选择开关。

1.废话不多说,我们先把ap选择开关的界面先做好,参考android7.1的内容我们很快就可以做好5.1的界面,具体过程因为比较简单,我就不啰嗦了,直接放上界面补丁,之后的framework处,我再详细分析说明:

cd packages/apps/Settings
diff --git a/res/layout/wifi_ap_dialog.xml b/res/layout/wifi_ap_dialog.xml
index 30043c4..f01ec7b 100644
--- a/res/layout/wifi_ap_dialog.xml
+++ b/res/layout/wifi_ap_dialog.xml
@@ -105,5 +105,30 @@
                     style="@style/wifi_item_content"
                     android:text="@string/wifi_show_password" />
         
-    
+	
+		
+
+			
+				
+
+				
+			
+		
+	
+	
 
diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml
index 826701e..07a937f 100755
--- a/res/values-zh-rCN/strings.xml
+++ b/res/values-zh-rCN/strings.xml
@@ -669,7 +669,11 @@
     "匿名身份"
     "密码"
     "显示密码"
-    "IP 设置"
+	
+	"选择 AP 频段"
+	"2.4 GHz 频段"
+	"5 GHz 频段"
+	"IP 设置"
     "(未更改)"
     "(未指定)"
     "已保存"
diff --git a/res/values/arrays.xml b/res/values/arrays.xml
index 3f8602c..b424068 100644
--- a/res/values/arrays.xml
+++ b/res/values/arrays.xml
@@ -420,6 +420,15 @@
         
         3
     
+	
+	
+	
+    	@string/wifi_ap_choose_2G
+    	@string/wifi_ap_choose_5G
+	
+	
+    	@string/wifi_ap_choose_2G
+	
 
     
     
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 068df77..9cbbf33 100755
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -1590,8 +1590,12 @@
     Password
     
     Show password
-    
-    IP settings
+	
+	
+	"Seleccionar banda de AP"
+	"2.4 GHz Band"
+	"5 GHz Band"
+	IP settings
     
     (unchanged)
     
diff --git a/src/com/android/settings/wifi/WifiApDialog.java b/src/com/android/settings/wifi/WifiApDialog.java
index fb8026a..6ec1f6c 100644
--- a/src/com/android/settings/wifi/WifiApDialog.java
+++ b/src/com/android/settings/wifi/WifiApDialog.java
@@ -22,12 +22,15 @@ import android.content.DialogInterface;
 import android.net.wifi.WifiConfiguration;
 import android.net.wifi.WifiConfiguration.AuthAlgorithm;
 import android.net.wifi.WifiConfiguration.KeyMgmt;
+import android.net.wifi.WifiManager;
 import android.os.Bundle;
 import android.text.Editable;
 import android.text.InputType;
 import android.text.TextWatcher;
+import android.util.Log;
 import android.view.View;
 import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
 import android.widget.CheckBox;
 import android.widget.EditText;
 import android.widget.Spinner;
@@ -35,6 +38,8 @@ import android.widget.TextView;
 
 import com.android.settings.R;
 
+import java.nio.charset.Charset;
+
 /**
  * Dialog to configure the SSID and security settings
  * for Access Point operation
@@ -53,8 +58,13 @@ public class WifiApDialog extends AlertDialog implements View.OnClickListener,
     private TextView mSsid;
     private int mSecurityTypeIndex = OPEN_INDEX;
     private EditText mPassword;
+    private int mBandIndex = OPEN_INDEX;
 
     WifiConfiguration mWifiConfig;
+    WifiManager mWifiManager;
+    private Context mContext;
+
+    private static final String TAG = "WifiApDialog";
 
     public WifiApDialog(Context context, DialogInterface.OnClickListener listener,
             WifiConfiguration wifiConfig) {
@@ -64,6 +74,8 @@ public class WifiApDialog extends AlertDialog implements View.OnClickListener,
         if (wifiConfig != null) {
             mSecurityTypeIndex = getSecurityTypeIndex(wifiConfig);
         }
+        mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
+        mContext =  context;
     }
 
     public static int getSecurityTypeIndex(WifiConfiguration wifiConfig) {
@@ -85,6 +97,8 @@ public class WifiApDialog extends AlertDialog implements View.OnClickListener,
          */
         config.SSID = mSsid.getText().toString();
 
+        config.apBand = mBandIndex;
+
         switch (mSecurityTypeIndex) {
             case OPEN_INDEX:
                 config.allowedKeyManagement.set(KeyMgmt.NONE);
@@ -104,9 +118,10 @@ public class WifiApDialog extends AlertDialog implements View.OnClickListener,
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
-
+        boolean mInit = true;
         mView = getLayoutInflater().inflate(R.layout.wifi_ap_dialog, null);
         Spinner mSecurity = ((Spinner) mView.findViewById(R.id.security));
+        final Spinner mChannel = (Spinner) mView.findViewById(R.id.choose_channel);
 
         setView(mView);
         setInverseBackgroundForced(true);
@@ -118,18 +133,68 @@ public class WifiApDialog extends AlertDialog implements View.OnClickListener,
         mSsid = (TextView) mView.findViewById(R.id.ssid);
         mPassword = (EditText) mView.findViewById(R.id.password);
 
+        ArrayAdapter  channelAdapter;
+        //String countryCode = mWifiManager.getCountryCode();
+        String countryCode = "CN"; //louhn:这里写死为CN
+		
+		if (countryCode == null) {
+            //If no country code, 5GHz AP is forbidden
+            Log.i(TAG,(!mWifiManager.isDualBandSupported() ? "Device do not support 5GHz " :"") 
+                    + (countryCode == null ? " NO country code" :"") +  " forbid 5GHz");
+            channelAdapter = ArrayAdapter.createFromResource(mContext,
+                    R.array.wifi_ap_band_config_2G_only, android.R.layout.simple_spinner_item);
+            mWifiConfig.apBand = 0;
+        } else {
+            channelAdapter = ArrayAdapter.createFromResource(mContext,
+                    R.array.wifi_ap_band_config_full, android.R.layout.simple_spinner_item);
+        }
+
+        channelAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+
         setButton(BUTTON_SUBMIT, context.getString(R.string.wifi_save), mListener);
         setButton(DialogInterface.BUTTON_NEGATIVE,
         context.getString(R.string.wifi_cancel), mListener);
 
         if (mWifiConfig != null) {
             mSsid.setText(mWifiConfig.SSID);
+            if (mWifiConfig.apBand == 0) {
+               mBandIndex = 0;
+            } else {
+               mBandIndex = 1;
+            }
+
             mSecurity.setSelection(mSecurityTypeIndex);
             if (mSecurityTypeIndex == WPA2_INDEX) {
-                  mPassword.setText(mWifiConfig.preSharedKey);
+                mPassword.setText(mWifiConfig.preSharedKey);
             }
         }
 
+        mChannel.setAdapter(channelAdapter);
+        mChannel.setOnItemSelectedListener(
+                new AdapterView.OnItemSelectedListener() {
+                    boolean mInit = true;
+                    @Override
+                    public void onItemSelected(AdapterView adapterView, View view, int position,
+                                               long id) {
+                        if (!mInit) {
+                            mBandIndex = position;
+                            mWifiConfig.apBand = mBandIndex;
+                            Log.i(TAG, "config on channelIndex : " + mBandIndex + " Band: " +
+                                    mWifiConfig.apBand);
+                        } else {
+                            mInit = false;
+                            mChannel.setSelection(mBandIndex);
+                        }
+
+                    }
+
+                    @Override
+                    public void onNothingSelected(AdapterView adapterView) {
+
+                    }
+                }
+        );
+
         mSsid.addTextChangedListener(this);
         mPassword.addTextChangedListener(this);
         ((CheckBox) mView.findViewById(R.id.show_password)).setOnClickListener(this);
@@ -141,10 +206,21 @@ public class WifiApDialog extends AlertDialog implements View.OnClickListener,
         validate();
     }
 
+    public void onRestoreInstanceState(Bundle savedInstanceState) {
+        super.onRestoreInstanceState(savedInstanceState);
+        mPassword.setInputType(
+                InputType.TYPE_CLASS_TEXT |
+                (((CheckBox) mView.findViewById(R.id.show_password)).isChecked() ?
+                InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD :
+                InputType.TYPE_TEXT_VARIATION_PASSWORD));
+    }
+
     private void validate() {
-        if ((mSsid != null && mSsid.length() == 0) ||
-                   ((mSecurityTypeIndex == WPA2_INDEX)&&
-                        mPassword.length() < 8)) {
+        String mSsidString = mSsid.getText().toString();
+        if ((mSsid != null && mSsid.length() == 0)
+                || ((mSecurityTypeIndex == WPA2_INDEX) && mPassword.length() < 8)
+                || (mSsid != null &&
+                Charset.forName("UTF-8").encode(mSsidString).limit() > 32)) {
             getButton(BUTTON_SUBMIT).setEnabled(false);
         } else {
             getButton(BUTTON_SUBMIT).setEnabled(true);

2.打上上面那个补丁后,你在界面上设置里面的“设置WLAN热点”的list里面应该就能看到2.4G和5G频段的热点选择开关,但是该开关没有作用,无论是选择2.4G还是5G,放出来的热点都是只有2.4G的。之后我们就来解决如何把5G AP的功能加入到5G的选择按钮上:

2.1、一开始我没有头绪,我们就从7.1的源码开始找思路,先把7.1的源码理顺了,再去修改5.1的代码。

我们从7.1的frameworks/opt/net/wifi/service/java/com/android/server/wifi/util/ApConfigUtil.java文件出发,看它是如何设置2.4G和5G的选择的:

public static int updateApChannelConfig(WifiNative wifiNative,
                                        String countryCode,
                                        ArrayList allowed2GChannels,
                                        WifiConfiguration config) {
    /* Use default band and channel for device without HAL. */
    if (!wifiNative.isHalStarted()) {
        //add by louhn
        if (WifiConfiguration.AP_BAND_2GHZ == config.apBand)
            config.apChannel = DEFAULT_AP_CHANNEL;
        else if (WifiConfiguration.AP_BAND_5GHZ == config.apBand)
            config.apChannel = DEFAULT_AP_CHANNEL_5GHz;
        else {
            config.apBand = DEFAULT_AP_BAND;
            config.apChannel = DEFAULT_AP_CHANNEL;
        }
        //add end
        return SUCCESS;
    }

在updateApChannelConfig方法里面是根据config.apBand这个值来设置判断现在选择的是2.4G还是5G,而这个config又是从哪里传来的呢?继续调查updateApChannelConfig是从哪里调用的。

2.2、搜索发现,frameworks/opt/net/wifi/service/java/com/android/server/wifi/SoftApManager.java目录下有调用updateApChannelConfig方法,直接进去看具体的情况:

private int startSoftAp(WifiConfiguration config) {
    if (config == null) {
        Log.e(TAG, "Unable to start soft AP without configuration");
        return ERROR_GENERIC;
    }

    /* Make a copy of configuration for updating AP band and channel. */
    WifiConfiguration localConfig = new WifiConfiguration(config);

    int result = ApConfigUtil.updateApChannelConfig(
            mWifiNative, mCountryCode, mAllowed2GChannels, localConfig);
    if (result != SUCCESS) {
        Log.e(TAG, "Failed to update AP band and channel");
        return result;
    }

    /* Setup country code if it is provide. */
    if (mCountryCode != null) {
        /**
         * Country code is mandatory for 5GHz band, return an error if failed to set
         * country code when AP is configured for 5GHz band.
         */

一个叫startSoftAp(WifiConfiguration config)方法里面,调用了updateApChannelConfig方法,而传入的localConfig就是我们要找的config,这个localConfig是WifiConfiguration localConfig =  WifiConfiguration(config);赋值的,我们再去查找startSoftAp是在哪里被调用的:

2.3、还是在frameworks/opt/net/wifi/service/java/com/android/server/wifi/SoftApManager.java目录下就有startSoftAp被调用的方法:

private class IdleState extends State {
    @Override
    public boolean processMessage(Message message) {
        switch (message.what) {
            case CMD_START:
                updateApState(WifiManager.WIFI_AP_STATE_ENABLING, 0);
                int result = startSoftAp((WifiConfiguration) message.obj);
                if (result == SUCCESS) {
                    updateApState(WifiManager.WIFI_AP_STATE_ENABLED, 0);
                    transitionTo(mStartedState);
                } else {
                    int reason = WifiManager.SAP_START_FAILURE_GENERAL;
                    if (result == ERROR_NO_CHANNEL) {
                        reason = WifiManager.SAP_START_FAILURE_NO_CHANNEL;
                    }
                    updateApState(WifiManager.WIFI_AP_STATE_FAILED, reason);
                }
                break;
            default:
                /* Ignore all other commands. */
                break;
        }
        return HANDLED;

而传入的值是message.obj,这里先把这个值放一边,先调查startSoftAp是如何被调用的,这里是switch进到case CMD_START后startSoftAp才被调用的,CMD_START字面意思我们试着去猜测一下:应该是处于开始打开AP的阶段,我们再在目录下搜索CMD_START是哪里被定义的:

private class SoftApStateMachine extends StateMachine {
    /* Commands for the state machine. */
    public static final int CMD_START = 0;
    public static final int CMD_STOP = 1;

    private final State mIdleState = new IdleState();
    private final State mStartedState = new StartedState();

    SoftApStateMachine(Looper looper) {
        super(TAG, looper);

        addState(mIdleState);
        addState(mStartedState, mIdleState);

        setInitialState(mIdleState);
        start();
    }

SoftApStateMachine类里面有对CMD_START的定义,那顺理成章的我们再搜索SoftApStateMachine.CMD_START是在哪里被使用到的:

/**
 * Start soft AP with given configuration.
 * @param config AP configuration
 */
public void start(WifiConfiguration config) {
    mStateMachine.sendMessage(SoftApStateMachine.CMD_START, config);
}

还是在当前目录,有个start方法,有发送SoftApStateMachine.CMD_START,继续搜索SoftApManager.start

2.4、在frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiStateMachine.java目录下,有调用mSoftApManager.start,我们进入源码查看:

 @Override
 public void enter() {
     final Message message = getCurrentMessage();
     if (message.what == CMD_START_AP) {
         WifiConfiguration config = (WifiConfiguration) message.obj;

         if (config == null) {
             /**
              * Configuration not provided in the command, fallback to use the current
              * configuration.
              */
             config = mWifiApConfigStore.getApConfiguration();
         } else {
             /* Update AP configuration. */
             mWifiApConfigStore.setApConfiguration(config);
         }

         checkAndSetConnectivityInstance();
         mSoftApManager = mFacade.makeSoftApManager(
                 mContext, getHandler().getLooper(), mWifiNative, mNwService,
                 mCm, mCountryCode.getCountryCode(),
                 mWifiApConfigStore.getAllowed2GChannel(),
                 new SoftApListener());
         mSoftApManager.start(config);
     } else {
         throw new RuntimeException("Illegal transition to SoftApState: " + message);
     }
 }
                                                                                              

mSoftApManager.start(config)是在Message接收到CMD_START_AP后执行的,而config值是WifiConfiguration config = (WifiConfiguration) message.obj赋值的,待会儿我们查看5.1代码时候,也进到这个目录下查看5.1在这个地方具体做了什么,我们再来看下config是怎么定义的,config的类是WifiConfiguration,我们直接搜索WifiConfiguration.java:

2.5:frameworks/base/wifi/java/android/net/wifi/WifiConfiguration.java:WifiConfiguration这个类里面定义了ssid,bssid,psk,scan_ssid等等等等,而之前我们的5G选择按钮AP_BAND_5GHZ也是在这里添加的,因为5.1压根就没有2.4G与5G的选择按钮,所以在5.1的WifiConfiguration.java目录下,也一定要添加对应的2.4G和5G的选择

因此我们回到5.1,在5.1上把WifiConfiguration.java文件里添加2.4G和5G的选择开关:

diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index 87db951..c9963b9 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -237,6 +237,36 @@ public class WifiConfiguration implements Parcelable {
      * Fully qualified domain name (FQDN) of AAA server or RADIUS server
      * e.g. {@code "mail.example.com"}.
      */
+	
+	/**
+	 * 2GHz band.
+	 * @hide
+	 */
+	public static final int AP_BAND_2GHZ = 0;
+
+	/**
+	 * 5GHz band.
+	 * @hide
+	 */
+	public static final int AP_BAND_5GHZ = 1;
+
+	/**
+	 * The band which AP resides on
+	 * 0-2G  1-5G
+	 * By default, 2G is chosen
+	 * @hide
+	 */
+	public int apBand = AP_BAND_2GHZ;
+
+	/**
+	 * The channel which AP resides on,currently, US only
+	 * 2G  1-11
+	 * 5G  36,40,44,48,149,153,157,161,165
+	 * 0 - find a random available channel according to the apBand
+	 * @hide
+	 */
+	public int apChannel = 0;
+	
     public String FQDN;
     /**
      * Network access identifier (NAI) realm, for Passpoint credential.
@@ -1500,7 +1530,10 @@ public class WifiConfiguration implements Parcelable {
             FQDN = source.FQDN;
             naiRealm = source.naiRealm;
             preSharedKey = source.preSharedKey;
-
+			//add by louhn
+			apBand = source.apBand;
+			apChannel = source.apChannel;
+			//add end
             wepKeys = new String[4];
             for (int i = 0; i < wepKeys.length; i++) {
                 wepKeys[i] = source.wepKeys[i];
@@ -1593,7 +1626,11 @@ public class WifiConfiguration implements Parcelable {
         dest.writeInt(disableReason);
         dest.writeString(SSID);
         dest.writeString(BSSID);
-        dest.writeString(autoJoinBSSID);
+        //add by louhn
+		dest.writeInt(apBand);
+		dest.writeInt(apChannel);
+		//end 
+		dest.writeString(autoJoinBSSID);
         dest.writeString(FQDN);
         dest.writeString(naiRealm);
         dest.writeString(preSharedKey);
@@ -1658,7 +1695,11 @@ public class WifiConfiguration implements Parcelable {
                 config.disableReason = in.readInt();
                 config.SSID = in.readString();
                 config.BSSID = in.readString();
-                config.autoJoinBSSID = in.readString();
+				//add by louhn
+                config.apBand = in.readInt();
+				config.apChannel = in.readInt();
+				//add end
+				config.autoJoinBSSID = in.readString();
                 config.FQDN = in.readString();
                 config.naiRealm = in.readString();
                 config.preSharedKey = in.readString();

再回到5.1的frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiStateMachine.java,查看5.1在SoftApState处具体做了什么:

 class SoftApStartingState extends State {
     @Override
     public void enter() {
         final Message message = getCurrentMessage();
         if (message.what == CMD_START_AP) {
             final WifiConfiguration config = (WifiConfiguration) message.obj;

             if (config == null) {
                 mWifiApConfigChannel.sendMessage(CMD_REQUEST_AP_CONFIG);
             } else {
                 mWifiApConfigChannel.sendMessage(CMD_SET_AP_CONFIG, config);
                 startSoftApWithConfig(config);
             }
         } else {
             throw new RuntimeException("Illegal transition to SoftApStartingState: " + message);
         }
     }
     @Override
     public boolean processMessage(Message message) {
         logStateAndMessage(message, getClass().getSimpleName());

         switch(message.what) {
             case CMD_START_SUPPLICANT:
            case CMD_STOP_SUPPLICANT:
            case CMD_START_AP:
            case CMD_STOP_AP:
            case CMD_START_DRIVER:
            case CMD_STOP_DRIVER:
            case CMD_SET_OPERATIONAL_MODE:
            case CMD_SET_COUNTRY_CODE:
            case CMD_SET_FREQUENCY_BAND:
            case CMD_START_PACKET_FILTERING:
            case CMD_STOP_PACKET_FILTERING:
            case CMD_TETHER_STATE_CHANGE:
                deferMessage(message);
                break;
            case WifiStateMachine.CMD_RESPONSE_AP_CONFIG:
                WifiConfiguration config = (WifiConfiguration) message.obj;
                if (config != null) {
                    startSoftApWithConfig(config);
                } else {
                    loge("Softap config is null!");
                    sendMessage(CMD_START_AP_FAILURE);
                }
                break;
            case CMD_START_AP_SUCCESS:
                setWifiApState(WIFI_AP_STATE_ENABLED);
                transitionTo(mSoftApStartedState);
                break;
            case CMD_START_AP_FAILURE:
                 setWifiApState(WIFI_AP_STATE_FAILED);
                 transitionTo(mInitialState);
                 break;
             default:
                 return NOT_HANDLED;
         }
         return HANDLED;
     }
 }

android5.1源码里面不叫SoftApState而是叫SoftApStartingState,这里有个判断if (config == null),则else执行startSoftApWithConfig(config),进入到startSoftApWithConfig方法,查看该方法具体做了什么:

还是在本目录下:

private void startSoftApWithConfig(final WifiConfiguration config) {
    // Start hostapd on a separate thread
    new Thread(new Runnable() {
        public void run() {
            try {
                mNwService.startAccessPoint(config, mInterfaceName);
            } catch (Exception e) {
                loge("Exception in softap start " + e);
                try {
                    mNwService.stopAccessPoint(mInterfaceName);
                    mNwService.startAccessPoint(config, mInterfaceName);
                } catch (Exception e1) {
                    loge("Exception in softap re-start " + e1);
                    sendMessage(CMD_START_AP_FAILURE);
                    return;
                }
            }
            if (DBG) log("Soft AP start successful");
            sendMessage(CMD_START_AP_SUCCESS);
            if(!mSoftApWakeLock.isHeld()) {
                loge("---- mSoftApWakeLock.acquire ----");
                mSoftApWakeLock.acquire();
            }
        }
    }).start();
}

该方法回去执行mNwService.startAccessPoint(config, mInterfaceName);我们再继续搜索mNwService.startAccessPoint做了什么

在frameworks/base/services/core/java/com/android/server/NetworkManagementService.java里,有对startAccessPoint的定义,进入目录,继续查看。终于,我们在startAccessPoint里找到了我们想看到的内容:

 mConnector.execute("softap", "set", wlanIface, wifiConfig.SSID,
                    "broadcast", "6", getSecurityType(wifiConfig),
                    new SensitiveArg(wifiConfig.preSharedKey));

设置wifi的SSID,信道等等,这里我们可以看到只传入了一个“6”,也就是说,只设置了2.4G的热点,那么我们可以在这里做一个选择,根据2.4G和5G的选择开关,去选择到底是打开2.4G还是5G:

diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java
index 18bf838..857fff4 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -1365,10 +1365,29 @@ public class NetworkManagementService extends INetworkManagementService.Stub
             if (wifiConfig == null) {
                 mConnector.execute("softap", "set", wlanIface);
             } else {
-                mConnector.execute("softap", "set", wlanIface, wifiConfig.SSID,
+				//add by louhn
+				if(wifiConfig.apBand == 0)//AP_BAND_2GHZ
+				{
+					mConnector.execute("softap", "set", wlanIface, wifiConfig.SSID,
+							           "broadcast", "6", getSecurityType(wifiConfig),
+									   new SensitiveArg(wifiConfig.preSharedKey));
+					Log.e("LOUHN", "wifiConfig.apBand: AP_BAND_2GHZ");
+				}
+				else if(wifiConfig.apBand == 1)//AP_BAND_5GHZ
+				{
+					mConnector.execute("softap", "set", wlanIface, wifiConfig.SSID,
+							           "broadcast", "153", getSecurityType(wifiConfig),
+										new SensitiveArg(wifiConfig.preSharedKey));
+					Log.e("LOUHN", "wifiConfig.apBand: AP_BAND_5GHZ");
+				}
+				else
+				{
+                	mConnector.execute("softap", "set", wlanIface, wifiConfig.SSID,
                                    "broadcast", "6", getSecurityType(wifiConfig),
                                    new SensitiveArg(wifiConfig.preSharedKey));
-            }
+            		Log.e("LOUHN", "Don't know wifiConfig.apBand");
+				}
+			}
             mConnector.execute("softap", "startap");
         } catch (NativeDaemonConnectorException e) {
             throw e.rethrowAsParcelableException();

最终编译烧写验证,该2.4G/5G开关生效。

你可能感兴趣的:(RK3288_Android,android)