Wifi源码学习之wifi连接

来源:互联网 发布:sql删除 编辑:程序博客网 时间:2024/06/03 05:06

wifi 连接,我们从 点击连接开始分析。

这里写图片描述

Settings\src\com\android\settings\wifi\WifiSettings.java

首先看到 onActivityCreate() 方法中写了三个Listener。(看名字就知道是监听者模式)
而这一切似乎都和 这个 WifiManager.java 息息相关。

@Overridepublic void onActivityCreated(Bundle savedInstanceState) {    super.onActivityCreated(savedInstanceState);    mWifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);    mConnectListener = new WifiManager.ActionListener() {                               @Override                               public void onSuccess() {                               }                               @Override                               public void onFailure(int reason) {                                   Activity activity = getActivity();                                   if (activity != null) {                                       Toast.makeText(activity,                                            R.string.wifi_failed_connect_message,                                            Toast.LENGTH_SHORT).show();                                   }                               }                           };    mSaveListener = new WifiManager.ActionListener() {                            @Override                            public void onSuccess() {                            }                            @Override                            public void onFailure(int reason) {                                Activity activity = getActivity();                                if (activity != null) {                                    Toast.makeText(activity,                                        R.string.wifi_failed_save_message,                                        Toast.LENGTH_SHORT).show();                                }                            }                        };    mForgetListener = new WifiManager.ActionListener() {                               @Override                               public void onSuccess() {                               }                               @Override                               public void onFailure(int reason) {                                   Activity activity = getActivity();                                   if (activity != null) {                                       Toast.makeText(activity,                                           R.string.wifi_failed_forget_message,                                           Toast.LENGTH_SHORT).show();                                   }                               }                           };......}

我们再找找注册这些监听的地方:
发现有两种连接方式:

protected void connect(final WifiConfiguration config) {    mWifiManager.connect(config, mConnectListener);}protected void connect(final int networkId) {    mWifiManager.connect(networkId, mConnectListener);}

在这儿被调用

@Overridepublic boolean onContextItemSelected(MenuItem item) {    // 我们再找找这个 mSelectedAccessPoint  变量在哪儿赋值    if (mSelectedAccessPoint == null) {        return super.onContextItemSelected(item);    }    switch (item.getItemId()) {   // 最终发现,连接的方法在这儿被调用。very good!        case MENU_ID_CONNECT: {            if (mSelectedAccessPoint.networkId != INVALID_NETWORK_ID) {                connect(mSelectedAccessPoint.networkId);            } else if (mSelectedAccessPoint.security == AccessPoint.SECURITY_NONE) {                /** Bypass dialog for unsecured networks */                mSelectedAccessPoint.generateOpenNetworkConfig();                connect(mSelectedAccessPoint.getConfig());            } else {                showDialog(mSelectedAccessPoint, true);            }            return true;        }        case MENU_ID_FORGET: {            forget();            return true;        }        case MENU_ID_MODIFY: {            showDialog(mSelectedAccessPoint, true);            return true;        }        case MENU_ID_WRITE_NFC:            showDialog(WRITE_NFC_DIALOG_ID);            return true;    }    return super.onContextItemSelected(item);}

最终发现,mSelectedAccessPoint 在这个方法中赋值

@Overridepublic boolean onPreferenceTreeClick(PreferenceScreen screen, Preference preference) {    if (preference instanceof AccessPoint) {        // 这个变量就是指当前点击的 wifi        mSelectedAccessPoint = (AccessPoint) preference;        /** Bypass dialog for unsecured, unsaved, and inactive networks */        if (mSelectedAccessPoint.security == AccessPoint.SECURITY_NONE &&                mSelectedAccessPoint.networkId == INVALID_NETWORK_ID &&                !mSelectedAccessPoint.isActive()) {            mSelectedAccessPoint.generateOpenNetworkConfig();            if (!savedNetworksExist) {                savedNetworksExist = true;                getActivity().invalidateOptionsMenu();            }            connect(mSelectedAccessPoint.getConfig());        } else {            showDialog(mSelectedAccessPoint, false);        }    } else {        return super.onPreferenceTreeClick(screen, preference);    }    return true;}

继续追踪 connect 方法:注释很多哈

/** * Connect to a network with the given configuration. The network also * gets added to the supplicant configuration. * * For a new network, this function is used instead of a * sequence of addNetwork(), enableNetwork(), saveConfiguration() and * reconnect() * * @param config the set of variables that describe the configuration, *            contained in a {@link WifiConfiguration} object. * @param listener for callbacks on success or failure. Can be null. * @throws IllegalStateException if the WifiManager instance needs to be * initialized again * * @hide */public void connect(WifiConfiguration config, ActionListener listener) {    if (config == null) throw new IllegalArgumentException("config cannot be null");    validateChannel();    // Use INVALID_NETWORK_ID for arg1 when passing a config object    // arg1 is used to pass network id when the network already exists    sAsyncChannel.sendMessage(CONNECT_NETWORK, WifiConfiguration.INVALID_NETWORK_ID,            putListener(listener), config);}/** * Connect to a network with the given networkId. * * This function is used instead of a enableNetwork(), saveConfiguration() and * reconnect() * * @param networkId the network id identifiying the network in the *                supplicant configuration list * @param listener for callbacks on success or failure. Can be null. * @throws IllegalStateException if the WifiManager instance needs to be * initialized again * @hide */public void connect(int networkId, ActionListener listener) {    if (networkId < 0) throw new IllegalArgumentException("Network id cannot be negative");    validateChannel();    sAsyncChannel.sendMessage(CONNECT_NETWORK, networkId, putListener(listener));}

继续追踪;原来 sAsyncChannel 是在这儿被创建的。

private void init() {    synchronized (sThreadRefLock) {        if (++sThreadRefCount == 1) {            Messenger messenger = getWifiServiceMessenger();            if (messenger == null) {                sAsyncChannel = null;                return;            }            sHandlerThread = new HandlerThread("WifiManager");   // 就是在这儿            sAsyncChannel = new AsyncChannel();            sConnected = new CountDownLatch(1);            sHandlerThread.start();            Handler handler = new ServiceHandler(sHandlerThread.getLooper());            // 这个connect 方法就是初始化的作用            sAsyncChannel.connect(mContext, handler, messenger);            try {                sConnected.await();            } catch (InterruptedException e) {                Log.e(TAG, "interrupted wait at init");            }        }    }}

然后我们回头看 它的 sendMessage() 方法到底干了什么。

frameworks\base\core\java\com\android\internal\util\AsyncChannel.java

public void sendMessage(int what, int arg1, int mListener, Object obj) {    Message msg = Message.obtain();    msg.what = what;    msg.arg1 = arg1;    // 我们的监听    msg.mListener= mListener;    msg.obj = obj;    sendMessage(msg);}

继续吧。

/** * Send a message to the destination handler. * * @param msg */public void sendMessage(Message msg) {    msg.replyTo = mSrcMessenger;    try {        mDstMessenger.send(msg);    } catch (RemoteException e) {        replyDisconnected(STATUS_SEND_UNSUCCESSFUL);    }}

找找这个 mDstMessenger 是从哪儿来的?
connected 方法,是不是很熟悉。刚刚在我们的 init()方法中。

public void connected(Context srcContext, Handler srcHandler, Messenger dstMessenger) {    if (DBG) log("connected srcHandler to the dstMessenger  E");    // Initialize source fields    mSrcContext = srcContext;    mSrcHandler = srcHandler;    mSrcMessenger = new Messenger(mSrcHandler);    // Initialize destination fields    mDstMessenger = dstMessenger;    if (DBG) log("connected srcHandler to the dstMessenger X");}
private void init() {    synchronized (sThreadRefLock) {        if (++sThreadRefCount == 1) {   // 最终发现            Messenger messenger = getWifiServiceMessenger();再往下看看吧!public Messenger getWifiServiceMessenger() {    try {        return mService.getWifiServiceMessenger();    } catch (RemoteException e) {        return null;    } catch (SecurityException e) {        return null;    }}

追踪 mService.在这儿赋值。

public WifiManager(Context context, IWifiManager service) {    mContext = context;    mService = service;    init();}

找找 WifiManager 初始化的地方:

frameworks\base\core\java\android\app\ContextImpl.java

Binder 进程间通信,咱就不再深究了。wifi 毕竟最终还是和硬件交互。registerService(WIFI_SERVICE, new ServiceFetcher() {        public Object createService(ContextImpl ctx) {            IBinder b = ServiceManager.getService(WIFI_SERVICE);            IWifiManager service = IWifiManager.Stub.asInterface(b);            return new WifiManager(ctx.getOuterContext(), service);        }});

连接成功,失败都是在回调中处理。其它的好像也没有什么了。

原创粉丝点击