Android 9.0打开wifi时关闭热点流程

it2025-12-19  7

  因发现Android 9.0 会在打开wifi的时候去默认关闭热点,所以我们看下打开wifi的流程,和在哪里去关闭的热点

1 设置打开wifi会调用

frameworks\base\wifi\java\android\net\wifi\WifiManager.java

/** * Enable or disable Wi-Fi. * <p> * Applications must have the {@link android.Manifest.permission#CHANGE_WIFI_STATE} * permission to toggle wifi. * * @param enabled {@code true} to enable, {@code false} to disable. * @return {@code false} if the request cannot be satisfied; {@code true} indicates that wifi is * either already in the requested state, or in progress toward the requested state. * @throws {@link java.lang.SecurityException} if the caller is missing required permissions. */ public boolean setWifiEnabled(boolean enabled) { try { return mService.setWifiEnabled(mContext.getOpPackageName(), enabled); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } }

2调用frameworks\opt\net\wifi\service\java\com\android\server\wifi\WifiServiceImpl.java 在这里有个判断热点状态的,我以为这里判断会有作用,后面发现没作用

/** * see {@link android.net.wifi.WifiManager#setWifiEnabled(boolean)} * @param enable {@code true} to enable, {@code false} to disable. * @return {@code true} if the enable/disable operation was * started or is already in the queue. */ @Override public synchronized boolean setWifiEnabled(String packageName, boolean enable) throws RemoteException { if (enforceChangePermission(packageName) != MODE_ALLOWED) { return false; } Slog.d(TAG, "setWifiEnabled: " + enable + " pid=" + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid() + ", package=" + packageName); mLog.info("setWifiEnabled package=% uid=% enable=%").c(packageName) .c(Binder.getCallingUid()).c(enable).flush(); boolean isFromSettings = checkNetworkSettingsPermission( Binder.getCallingPid(), Binder.getCallingUid()); // If Airplane mode is enabled, only Settings is allowed to toggle Wifi if (mSettingsStore.isAirplaneModeOn() && !isFromSettings) { mLog.info("setWifiEnabled in Airplane mode: only Settings can enable wifi").flush(); return false; } // If SoftAp is enabled, only Settings is allowed to toggle wifi boolean apEnabled = mWifiApState == WifiManager.WIFI_AP_STATE_ENABLED; if (apEnabled && !isFromSettings) { mLog.info("setWifiEnabled SoftAp not disabled: only Settings can enable wifi").flush(); return false; } /* * Caller might not have WRITE_SECURE_SETTINGS, * only CHANGE_WIFI_STATE is enforced */ long ident = Binder.clearCallingIdentity(); try { if (! mSettingsStore.handleWifiToggled(enable)) { // Nothing to do if wifi cannot be toggled return true; } } finally { Binder.restoreCallingIdentity(ident); } if (mPermissionReviewRequired) { final int wiFiEnabledState = getWifiEnabledState(); if (enable) { if (wiFiEnabledState == WifiManager.WIFI_STATE_DISABLING || wiFiEnabledState == WifiManager.WIFI_STATE_DISABLED) { if (startConsentUi(packageName, Binder.getCallingUid(), WifiManager.ACTION_REQUEST_ENABLE)) { return true; } } } else if (wiFiEnabledState == WifiManager.WIFI_STATE_ENABLING || wiFiEnabledState == WifiManager.WIFI_STATE_ENABLED) { if (startConsentUi(packageName, Binder.getCallingUid(), WifiManager.ACTION_REQUEST_DISABLE)) { return true; } } } mWifiController.sendMessage(CMD_WIFI_TOGGLED); return true; }

3,上面代码没有开关热点操作,接着流程经历了一些状态传递,这里就不贴代码了,可以自己去看看下面几个类或者找一篇分析wifi开启流程的文章,frameworks\opt\net\wifi\service\java\com\android\server\wifi\WifiController.java

接着来到frameworks\opt\net\wifi\service\java\com\android\server\wifi\ScanOnlyModeManager.java

private class IdleState extends State { @Override public void enter() { Log.d(TAG, "entering IdleState"); mClientInterfaceName = null; } @Override public boolean processMessage(Message message) { switch (message.what) { case CMD_START: mClientInterfaceName = mWifiNative.setupInterfaceForClientMode(true, mWifiNativeInterfaceCallback); if (TextUtils.isEmpty(mClientInterfaceName)) { Log.e(TAG, "Failed to create ClientInterface. Sit in Idle"); updateWifiState(WifiManager.WIFI_STATE_UNKNOWN); break; } // we have a new scanning interface, make sure scanner knows we aren't // ready yet and clear out the ScanRequestProxy sendScanAvailableBroadcast(false); // explicitly disable scanning for hidden networks in case we were // previously in client mode mScanRequestProxy.enableScanningForHiddenNetworks(false); mScanRequestProxy.clearScanResults(); transitionTo(mStartedState); break; default: Log.d(TAG, "received an invalid message: " + message); return NOT_HANDLED; } return HANDLED; } }

这里我们查看setupInterfaceForClientMode方法

frameworks\base\wifi\java\android\net\wifi\WifiManager.java

/** * Setup an interface for Client mode operations. * * This method configures an interface in STA mode in all the native daemons * (wificond, wpa_supplicant & vendor HAL). * * @param lowPrioritySta The requested STA has a low request priority (lower probability of * getting created, higher probability of getting destroyed). * @param interfaceCallback Associated callback for notifying status changes for the iface. * @return Returns the name of the allocated interface, will be null on failure. */ public String setupInterfaceForClientMode(boolean lowPrioritySta, @NonNull InterfaceCallback interfaceCallback) { synchronized (mLock) { if (!startHal()) { Log.e(TAG, "Failed to start Hal"); mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToHal(); return null; } if (!startSupplicant()) { Log.e(TAG, "Failed to start supplicant"); mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToSupplicant(); return null; } Iface iface = mIfaceMgr.allocateIface(Iface.IFACE_TYPE_STA); if (iface == null) { Log.e(TAG, "Failed to allocate new STA iface"); return null; } iface.externalListener = interfaceCallback; iface.name = createStaIface(iface, lowPrioritySta); if (TextUtils.isEmpty(iface.name)) { Log.e(TAG, "Failed to create STA iface in vendor HAL"); mIfaceMgr.removeIface(iface.id); mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToHal(); return null; } if (mWificondControl.setupInterfaceForClientMode(iface.name) == null) { Log.e(TAG, "Failed to setup iface in wificond on " + iface); teardownInterface(iface.name); mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToWificond(); return null; } if (!mSupplicantStaIfaceHal.setupIface(iface.name)) { Log.e(TAG, "Failed to setup iface in supplicant on " + iface); teardownInterface(iface.name); mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToSupplicant(); return null; } iface.networkObserver = new NetworkObserverInternal(iface.id); if (!registerNetworkObserver(iface.networkObserver)) { Log.e(TAG, "Failed to register network observer on " + iface); teardownInterface(iface.name); return null; } mWifiMonitor.startMonitoring(iface.name); // Just to avoid any race conditions with interface state change callbacks, // update the interface state before we exit. onInterfaceStateChanged(iface, isInterfaceUp(iface.name)); initializeNwParamsForClientInterface(iface.name); Log.i(TAG, "Successfully setup " + iface); return iface.name; } }

可以看到这是过去需要开启wifi的设备节点的地方,然后查看createStaIface方法

/** * Helper function to handle creation of STA iface. * For devices which do not the support the HAL, this will bypass HalDeviceManager & * teardown any existing iface. */ private String createStaIface(@NonNull Iface iface, boolean lowPrioritySta) { synchronized (mLock) { if (mWifiVendorHal.isVendorHalSupported()) { return mWifiVendorHal.createStaIface(lowPrioritySta, new InterfaceDestoyedListenerInternal(iface.id)); } else { Log.i(TAG, "Vendor Hal not supported, ignoring createStaIface."); //通过打印LOG发现最终我这套代码是走到了这里 return handleIfaceCreationWhenVendorHalNotSupported(iface); } } }

接着查看handleIfaceCreationWhenVendorHalNotSupported

// For devices that don't support the vendor HAL, we will not support any concurrency. // So simulate the HalDeviceManager behavior by triggering the destroy listener for // any active interface. private String handleIfaceCreationWhenVendorHalNotSupported(@NonNull Iface newIface) { synchronized (mLock) { Iface existingIface = mIfaceMgr.removeExistingIface(newIface.id); if (existingIface != null) { onInterfaceDestroyed(existingIface); Log.i(TAG, "Successfully torn down " + existingIface); } // Return the interface name directly from the system property. return mPropertyService.getString("wifi.interface", "wlan0"); } } /** Helper method invoked to teardown iface and perform necessary cleanup */ private void onInterfaceDestroyed(@NonNull Iface iface) { synchronized (mLock) { if (iface.type == Iface.IFACE_TYPE_STA) { onClientInterfaceDestroyed(iface); } else if (iface.type == Iface.IFACE_TYPE_AP) { onSoftApInterfaceDestroyed(iface);//这里最终执行了关闭热点 } // Invoke the external callback. iface.externalListener.onDestroyed(iface.name); } }

通过上述可以发现,我们只需要修改onInterfaceDestroyed handleIfaceCreationWhenVendorHalNotSupported createStaIface三个方法中的任何一个就可以让开wifi时不要不关闭热点,当然个人建议修改createStaIface方法

最新回复(0)