(八十九) Android O 探索WiFi直连默认名称由来

1.Settings

WifiP2pSettings

布局文件为wifi_p2p_settings

    @Override
    protected int getPreferenceScreenResId() {
        return R.xml.wifi_p2p_settings;
    }
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
    <Preference
        android:key="p2p_this_device"
        android:selectable="false" />
    <PreferenceCategory
        android:key="p2p_peer_devices"
        android:title="@string/wifi_p2p_peer_devices" />
    <PreferenceCategory
        android:key="p2p_persistent_group"
        android:title="@string/wifi_p2p_remembered_groups" />
</PreferenceScreen>

默认布局文件中对应设备名称显示的是p2p_this_device。

    @Override
    protected List<AbstractPreferenceController> getPreferenceControllers(Context context) {
        final List<AbstractPreferenceController> controllers = new ArrayList<>();
        mPersistentCategoryController =
                new P2pPersistentCategoryPreferenceController(context);
        mPeerCategoryController =
                new P2pPeerCategoryPreferenceController(context);
        mThisDevicePreferenceController = new P2pThisDevicePreferenceController(context);
        controllers.add(mPersistentCategoryController);
        controllers.add(mPeerCategoryController);
        controllers.add(mThisDevicePreferenceController);
        return controllers;
    }

对应的是P2pThisDevicePreferenceController控制的,WifiP2pSettings监听到了WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION会触发mThisDevicePreferenceController更新设备名称

            } else if (WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION.equals(action)) {
                mThisDevice = (WifiP2pDevice) intent.getParcelableExtra(
                        WifiP2pManager.EXTRA_WIFI_P2P_DEVICE);
                if (DBG) Log.d(TAG, "Update device info: " + mThisDevice);
                mThisDevicePreferenceController.updateDeviceName(mThisDevice);
            } 

 

    public void updateDeviceName(WifiP2pDevice thisDevice) {
        if (mPreference != null && thisDevice != null) {
            if (TextUtils.isEmpty(thisDevice.deviceName)) {
                mPreference.setTitle(thisDevice.deviceAddress);
            } else {
                mPreference.setTitle(thisDevice.deviceName);
            }
        }
    }

 

2.WifiP2pServiceimpl

对应的是WifiP2pServiceimpl发出的 WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION广播消息

        private void sendThisDeviceChangedBroadcast() {
            final Intent intent = new Intent(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION);
            intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
            intent.putExtra(WifiP2pManager.EXTRA_WIFI_P2P_DEVICE, new WifiP2pDevice(mThisDevice));
            mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
        }

看下最初mThisDevice是如何初始化的:

注意到mThisDevice初始实现deviceName为“”,另外发现在P2pEnabledState的enter方法中有初始化mThisDevice.deviceName的逻辑。

1.private WifiP2pDevice mThisDevice = new WifiP2pDevice();
//默认实现,deviceName为空字符串
    /**
     * The device name is a user friendly string to identify a Wi-Fi p2p device
     */
    public String deviceName = "";


2.
        class P2pEnabledState extends State {
            @Override
            public void enter() {
                if (DBG) logd(getName());
                sendP2pStateChangedBroadcast(true);
                mNetworkInfo.setIsAvailable(true);
                sendP2pConnectionChangedBroadcast();
                initializeP2pSettings();
            }

3.

        private void initializeP2pSettings() {
            mThisDevice.deviceName = getPersistedDeviceName();
            mWifiNative.setP2pDeviceName(mThisDevice.deviceName);
            // DIRECT-XY-DEVICENAME (XY is randomly generated)
            mWifiNative.setP2pSsidPostfix("-" + mThisDevice.deviceName);
            mWifiNative.setP2pDeviceType(mThisDevice.primaryDeviceType);
            // Supplicant defaults to using virtual display with display
            // which refers to a remote display. Use physical_display
            mWifiNative.setConfigMethods("virtual_push_button physical_display keypad");

            mThisDevice.deviceAddress = mWifiNative.p2pGetDeviceAddress();
            updateThisDevice(WifiP2pDevice.AVAILABLE);
            if (DBG) logd("DeviceAddress: " + mThisDevice.deviceAddress);

            mClientInfoList.clear();
            mWifiNative.p2pFlush();
            mWifiNative.p2pServiceFlush();
            mServiceTransactionId = 0;
            mServiceDiscReqId = null;

            updatePersistentNetworks(RELOAD);
        }

4.默认deviceName实现
        private String getPersistedDeviceName() {
            String deviceName = Settings.Global.getString(mContext.getContentResolver(),
                    Settings.Global.WIFI_P2P_DEVICE_NAME);
            if (deviceName == null) {
                // We use the 4 digits of the ANDROID_ID to have a friendly
                // default that has low likelihood of collision with a peer
                String id = Settings.Secure.getString(mContext.getContentResolver(),
                        Settings.Secure.ANDROID_ID);
                return "Android_" + id.substring(0, 4);
            }
            return deviceName;
        }

5.发出广播表示信息更新
        private void updateThisDevice(int status) {
            mThisDevice.status = status;
            sendThisDeviceChangedBroadcast();
        }

看下何时会切换到P2pEnabledState状态

先看下WifiP2pServiceimpl状态机结构,另外搜了一下没有直接的状态会切换到P2pEnabledState,所以应该是切换其子状态过程中走了P2pEnabledState的enter方法。

            addState(mDefaultState);
                addState(mP2pNotSupportedState, mDefaultState);
                addState(mP2pDisablingState, mDefaultState);
                addState(mP2pDisabledState, mDefaultState);
                addState(mP2pEnablingState, mDefaultState);
                addState(mP2pEnabledState, mDefaultState);
                    addState(mInactiveState, mP2pEnabledState);
                    addState(mGroupCreatingState, mP2pEnabledState);
                        addState(mUserAuthorizingInviteRequestState, mGroupCreatingState);
                        addState(mUserAuthorizingNegotiationRequestState, mGroupCreatingState);
                        addState(mProvisionDiscoveryState, mGroupCreatingState);
                        addState(mGroupNegotiationState, mGroupCreatingState);
                        addState(mFrequencyConflictState, mGroupCreatingState);
                    addState(mGroupCreatedState, mP2pEnabledState);
                        addState(mUserAuthorizingJoinState, mGroupCreatedState);
                        addState(mOngoingGroupRemovalState, mGroupCreatedState);

            if (p2pSupported) {
                setInitialState(mP2pDisabledState);
            } else {
                setInitialState(mP2pNotSupportedState);
            }

初始状态一般为mP2pDisabledState

        class P2pDisabledState extends State {
            @Override
            public void enter() {
                if (DBG) logd(getName());
            }

            @Override
            public boolean processMessage(Message message) {
                if (DBG) logd(getName() + message.toString());
                switch (message.what) {
                    case WifiStateMachine.CMD_ENABLE_P2P:
                        try {
                            mNwService.setInterfaceUp(mWifiNative.getInterfaceName());
                        } catch (RemoteException re) {
                            loge("Unable to change interface settings: " + re);
                        } catch (IllegalStateException ie) {
                            loge("Unable to change interface settings: " + ie);
                        }
                        mWifiMonitor.startMonitoring(mWifiNative.getInterfaceName());
                        transitionTo(mP2pEnablingState);
                        break;
                    default:
                        return NOT_HANDLED;
                }
                return HANDLED;
            }
        }

之后肯定是接收到了WifiStateMachine.CMD_ENABLE_P2P消息切换到mP2pEnablingState,主要到如下和WifiStateMachine启动supplicant状态切换相似的逻辑

mWifiMonitor.startMonitoring(mWifiNative.getInterfaceName());

    /**
     * Start Monitoring for wpa_supplicant events.
     *
     * @param iface Name of iface.
     * TODO: Add unit tests for these once we remove the legacy code.
     */
    public synchronized void startMonitoring(String iface, boolean isStaIface) {
        if (ensureConnectedLocked()) {
            setMonitoring(iface, true);
            broadcastSupplicantConnectionEvent(iface);
        } else {
            boolean originalMonitoring = isMonitoring(iface);
            setMonitoring(iface, true);
            broadcastSupplicantDisconnectionEvent(iface);
            setMonitoring(iface, originalMonitoring);
            Log.e(TAG, "startMonitoring(" + iface + ") failed!");
        }
    }

    /**
     * Broadcast the connection to wpa_supplicant event to all the handlers registered for
     * this event.
     *
     * @param iface Name of iface on which this occurred.
     */
    public void broadcastSupplicantConnectionEvent(String iface) {
        sendMessage(iface, SUP_CONNECTION_EVENT);
    }

这边也类似,connect完了之后会发出SUP_CONNECTION_EVENT消息,WifiP2pServiceImpl也注册了消息监听

            mWifiMonitor.registerHandler(interfaceName,
                    WifiP2pMonitor.SUP_CONNECTION_EVENT, getHandler());
        class P2pEnablingState extends State {
            @Override
            public void enter() {
                if (DBG) logd(getName());
            }

            @Override
            public boolean processMessage(Message message) {
                if (DBG) logd(getName() + message.toString());
                switch (message.what) {
                    case WifiP2pMonitor.SUP_CONNECTION_EVENT:
                        if (DBG) logd("P2p socket connection successful");
                        transitionTo(mInactiveState);
                        break;
                    case WifiP2pMonitor.SUP_DISCONNECTION_EVENT:
                        loge("P2p socket connection failed");
                        transitionTo(mP2pDisabledState);
                        break;
                    case WifiStateMachine.CMD_ENABLE_P2P:
                    case WifiStateMachine.CMD_DISABLE_P2P_REQ:
                        deferMessage(message);
                        break;
                    default:
                        return NOT_HANDLED;
                }
                return HANDLED;
            }
        }

接着接收到SUP_CONNECTION_EVENT切换到了mInactiveState,该状态的父状态为mP2pEnabledState。

再回头看下WifiStateMachine是何时发出的WifiStateMachine.CMD_ENABLE_P2P

    class SupplicantStartedState extends State {
        @Override
        public void enter() {
            if (mVerboseLoggingEnabled) {
                logd("SupplicantStartedState enter");
            }

...

            if (mP2pSupported) {
                if (mOperationalMode == CONNECT_MODE) {
                    p2pSendMessage(WifiStateMachine.CMD_ENABLE_P2P);
              } else {
                    // P2P state machine starts in disabled state, and is not enabled until
                    // CMD_ENABLE_P2P is sent from here; so, nothing needs to be done to
                    // keep it disabled.
                }
            }

            final Intent intent = new Intent(WifiManager.WIFI_SCAN_AVAILABLE);
            intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
            intent.putExtra(WifiManager.EXTRA_SCAN_AVAILABLE, WIFI_STATE_ENABLED);
            mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);

            // Disable wpa_supplicant from auto reconnecting.
            mWifiNative.enableStaAutoReconnect(false);
            // STA has higher priority over P2P
            mWifiNative.setConcurrencyPriority(true);
        }

WifiStateMachine在supplicant启动完成状态切换到SupplicantStartedState就会发出WifiStateMachine.CMD_ENABLE_P2P触使enable p2p。

    /**
     * Send message to WifiP2pServiceImpl.
     * @return true if message is sent.
     *         false if there is no channel configured for WifiP2pServiceImpl.
     */
    private boolean p2pSendMessage(int what) {
        if (mWifiP2pChannel != null) {
            mWifiP2pChannel.sendMessage(what);
            return true;
        }
        return false;
    }

    /**
     * WifiStateMachine needs to enable/disable other services when wifi is in client mode.  This
     * method allows WifiStateMachine to get these additional system services.
     *
     * At this time, this method is used to setup variables for P2P service and Wifi Aware.
     */
    private void getAdditionalWifiServiceInterfaces() {
        // First set up Wifi Direct
        if (mP2pSupported) {
            IBinder s1 = mFacade.getService(Context.WIFI_P2P_SERVICE);
            WifiP2pServiceImpl wifiP2pServiceImpl =
                    (WifiP2pServiceImpl) IWifiP2pManager.Stub.asInterface(s1);

            if (wifiP2pServiceImpl != null) {
                mWifiP2pChannel = new AsyncChannel();
                mWifiP2pChannel.connect(mContext, getHandler(),
                        wifiP2pServiceImpl.getP2pStateMachineMessenger());
            }
        }
    }

DefaultState会处理CMD_BOOT_COMPLETED并与WiFiP2pServiceImpl建立连接。

                case CMD_BOOT_COMPLETED:
                    // get other services that we need to manage
                    getAdditionalWifiServiceInterfaces();
                    if (!mWifiConfigManager.loadFromStore()) {
                        Log.e(TAG, "Failed to load from config store");
                    }
                    maybeRegisterNetworkFactory();
                    maybeRegisterPhoneListener();
                    break;



        mContext.registerReceiver(
                new BroadcastReceiver() {
                    @Override
                    public void onReceive(Context context, Intent intent) {
                        sendMessage(CMD_BOOT_COMPLETED);
                    }
                },
                new IntentFilter(Intent.ACTION_LOCKED_BOOT_COMPLETED));

 

3.总结

至于修改默认名称只要修改

WifiP2pServiceImpl的如下接口实现即可


        private String getPersistedDeviceName() {
            String deviceName = Settings.Global.getString(mContext.getContentResolver(),
                    Settings.Global.WIFI_P2P_DEVICE_NAME);
            if (deviceName == null) {
                // We use the 4 digits of the ANDROID_ID to have a friendly
                // default that has low likelihood of collision with a peer
                String id = Settings.Secure.getString(mContext.getContentResolver(),
                        Settings.Secure.ANDROID_ID);
                return "Android_" + id.substring(0, 4);
            }
            return deviceName;
}

 

相关推荐
©️2020 CSDN 皮肤主题: 鲸 设计师:meimeiellie 返回首页