(两百零一) 探讨p2p0的粘性
作者:互联网
前言:在平常工作中,注意到关闭热点后,p2p0就自己起来了,而这是自己又没操作p2p相关的应用,这是为什么呢?
1.p2p0自启动流程
// Check & re-enable P2P if needed.
// P2P interface will be created if all of the below are true:
// a) Wifi is enabled.
// b) HAL (HIDL) interface is available.
// c) There is atleast 1 client app which invoked initialize().
private void checkAndReEnableP2p() {
boolean isHalInterfaceAvailable = isHalInterfaceAvailable();
Log.d(TAG, "Wifi enabled=" + mIsWifiEnabled + ", P2P Interface availability="
+ isHalInterfaceAvailable + ", Number of clients="
+ mDeathDataByBinder.size());
if (mIsWifiEnabled && isHalInterfaceAvailable
&& !mDeathDataByBinder.isEmpty()) {
sendMessage(ENABLE_P2P);
}
}
WifiP2pServiceImpl中有个关键的方法叫做checkAndReEnableP2p,这个方法会在满足如下3个条件的时候将p2p创建出来
- WiFi已打开
- hal 接口是可获取的(即p2p0是可创建的)
- 至少有一个app客户端调用了initialize,即有p2p请求
checkAndReEnableP2p在什么时候会被调用呢?
1)WiFi开启的时候
// Register for wifi on/off broadcasts
mContext.registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
int wifistate = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
WifiManager.WIFI_STATE_UNKNOWN);
if (wifistate == WifiManager.WIFI_STATE_ENABLED) {
mIsWifiEnabled = true;
checkAndReEnableP2p();
} else {
mIsWifiEnabled = false;
// Teardown P2P if it's up already.
sendMessage(DISABLE_P2P);
}
checkAndSendP2pStateChangedBroadcast();
}
}, new IntentFilter(WifiManager.WIFI_STATE_CHANGED_ACTION));
2)p2p接口可创建的时候
// Register for interface availability from HalDeviceManager
mWifiNative.registerInterfaceAvailableListener((boolean isAvailable) -> {
mIsHalInterfaceAvailable = isAvailable;
if (isAvailable) {
checkAndReEnableP2p();
}
checkAndSendP2pStateChangedBroadcast();
}, getHandler());
PS: android 在Q上修改了当gps为关的时候,WiFi直连开关为灰显状态,原因这边看到了:当gps关闭的时候,p2p会停止扫描
// Register for location mode on/off broadcasts
mContext.registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
/* if location mode is off, ongoing discovery should be stopped.
* possible ongoing discovery:
* - peer discovery
* - service discovery
* - group joining scan in native service
*/
if (!mWifiPermissionsUtil.isLocationModeEnabled()) {
sendMessage(WifiP2pManager.STOP_DISCOVERY);
}
}
}, new IntentFilter(LocationManager.MODE_CHANGED_ACTION));
2.何为p2p0可创建?
我们可以顺着下面的这个方法往下看
// Register for interface availability from HalDeviceManager
mWifiNative.registerInterfaceAvailableListener((boolean isAvailable) -> {
mIsHalInterfaceAvailable = isAvailable;
if (isAvailable) {
checkAndReEnableP2p();
}
checkAndSendP2pStateChangedBroadcast();
}, getHandler());
这边通过WifiP2pNative创建了一个回调,当接口可获取性有变化的时候会通知到WifiP2pServiceImpl,然后由WifiP2pServiceImpl决定是否重新创建p2p,另外会发送一个p2p状态改变的广播出来。
private void checkAndSendP2pStateChangedBroadcast() {
boolean isHalInterfaceAvailable = isHalInterfaceAvailable();
Log.d(TAG, "Wifi enabled=" + mIsWifiEnabled + ", P2P Interface availability="
+ isHalInterfaceAvailable);
sendP2pStateChangedBroadcast(mIsWifiEnabled && isHalInterfaceAvailable);
}
private void sendP2pStateChangedBroadcast(boolean enabled) {
final Intent intent = new Intent(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
if (enabled) {
intent.putExtra(WifiP2pManager.EXTRA_WIFI_STATE,
WifiP2pManager.WIFI_P2P_STATE_ENABLED);
} else {
intent.putExtra(WifiP2pManager.EXTRA_WIFI_STATE,
WifiP2pManager.WIFI_P2P_STATE_DISABLED);
}
mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
}
2.1 WifiP2pNative
/**
* Register for an interface available callbacks from HalDeviceManager.
*
* @param listener callback to be invoked when the interface is available/not available.
*/
public void registerInterfaceAvailableListener(
@NonNull HalDeviceManager.InterfaceAvailableForRequestListener listener,
Handler handler) {
mInterfaceAvailableListener = new InterfaceAvailableListenerInternal(listener);
// The interface available callbacks are cleared on every HAL stop, so need to
// re-register these callbacks on every start.
mHalDeviceManager.registerStatusListener(() -> {
if (mHalDeviceManager.isStarted()) {
Log.i(TAG, "Registering for interface available listener");
mHalDeviceManager.registerInterfaceAvailableForRequestListener(
IfaceType.P2P, mInterfaceAvailableListener, handler);
}
}, handler);
if (mHalDeviceManager.isStarted()) {
mHalDeviceManager.registerInterfaceAvailableForRequestListener(
IfaceType.P2P, mInterfaceAvailableListener, handler);
}
}
这边把监听器包装了下
// Internal callback registered to HalDeviceManager.
private class InterfaceAvailableListenerInternal implements
HalDeviceManager.InterfaceAvailableForRequestListener {
private final HalDeviceManager.InterfaceAvailableForRequestListener mExternalListener;
InterfaceAvailableListenerInternal(
HalDeviceManager.InterfaceAvailableForRequestListener externalListener) {
mExternalListener = externalListener;
}
@Override
public void onAvailabilityChanged(boolean isAvailable) {
Log.d(TAG, "P2P InterfaceAvailableListener " + isAvailable);
// We need another level of abstraction here. When a P2P interface is created,
// we should mask the availability change callback from WifiP2pService.
// This is because when the P2P interface is created, we'll get a callback
// indicating that we can no longer create a new P2P interface. We don't need to
// propagate this internal state to WifiP2pServiceImpl.
if (mIWifiP2pIface != null && !isAvailable) {
Log.i(TAG, "Masking interface non-availability callback because "
+ "we created a P2P iface");
return;
}
mExternalListener.onAvailabilityChanged(isAvailable);
}
}
主要是为了当主动创建p2p的时候,回调不要往上报
2.2 HalDeviceManager
/**
* Register a listener to be called when an interface of the specified type could be requested.
* No guarantees are provided (some other entity could request it first). The listener is
* active from registration until unregistration - using
* unregisterInterfaceAvailableForRequestListener().
*
* Only a single instance of a listener will be registered (even if the specified looper is
* different).
*
* Note that if it is possible to create the specified interface type at registration time
* then the callback will be triggered immediately.
*
* @param ifaceType The interface type (IfaceType) to be monitored.
* @param listener Listener to call when an interface of the requested
* type could be created
* @param handler Handler on which to dispatch listener. Null implies the listener will be
* invoked synchronously from the context of the client which triggered the
* mode change.
*/
public void registerInterfaceAvailableForRequestListener(int ifaceType,
@NonNull InterfaceAvailableForRequestListener listener, @Nullable Handler handler) {
if (VDBG) {
Log.d(TAG, "registerInterfaceAvailableForRequestListener: ifaceType=" + ifaceType
+ ", listener=" + listener + ", handler=" + handler);
}
synchronized (mLock) {
InterfaceAvailableForRequestListenerProxy proxy =
new InterfaceAvailableForRequestListenerProxy(listener, handler);
if (mInterfaceAvailableForRequestListeners.get(ifaceType).containsKey(proxy)) {
if (VDBG) {
Log.d(TAG,
"registerInterfaceAvailableForRequestListener: dup listener skipped: "
+ listener);
}
return;
}
mInterfaceAvailableForRequestListeners.get(ifaceType).put(proxy, null);
}
WifiChipInfo[] chipInfos = getAllChipInfo();
if (chipInfos == null) {
Log.e(TAG,
"registerInterfaceAvailableForRequestListener: no chip info found - but "
+ "possibly registered pre-started - ignoring");
return;
}
dispatchAvailableForRequestListenersForType(ifaceType, chipInfos);
}
这边又包了一层代理,然后放到特定的SparseArray里去
private class InterfaceAvailableForRequestListenerProxy extends
ListenerProxy<InterfaceAvailableForRequestListener> {
InterfaceAvailableForRequestListenerProxy(
InterfaceAvailableForRequestListener destroyedListener, Handler handler) {
super(destroyedListener, handler, "InterfaceAvailableForRequestListenerProxy");
}
@Override
protected void actionWithArg(boolean isAvailable) {
mListener.onAvailabilityChanged(isAvailable);
}
}
private abstract class ListenerProxy<LISTENER> {
protected LISTENER mListener;
private Handler mHandler;
// override equals & hash to make sure that the container HashSet is unique with respect to
// the contained listener
@Override
public boolean equals(Object obj) {
return mListener == ((ListenerProxy<LISTENER>) obj).mListener;
}
@Override
public int hashCode() {
return mListener.hashCode();
}
void trigger() {
if (mHandler != null) {
mHandler.post(() -> {
action();
});
} else {
action();
}
}
void triggerWithArg(boolean arg) {
if (mHandler != null) {
mHandler.post(() -> {
actionWithArg(arg);
});
} else {
actionWithArg(arg);
}
}
protected void action() {}
protected void actionWithArg(boolean arg) {}
ListenerProxy(LISTENER listener, Handler handler, String tag) {
mListener = listener;
mHandler = handler;
}
}
这里写了两个点,一个是相同的listener只能注册一次,和handler没关系,另外如果是指定传递handler进来,那边可以指定在对应handler里执行回调。
注册回调后会立刻触发一次interface可创建性检查,如果当前可创建性与当前已保存状态不一致,触发回调
private void dispatchAvailableForRequestListenersForType(int ifaceType,
WifiChipInfo[] chipInfos) {
if (VDBG) Log.d(TAG, "dispatchAvailableForRequestListenersForType: ifaceType=" + ifaceType);
synchronized (mLock) {
Map<InterfaceAvailableForRequestListenerProxy, Boolean> listeners =
mInterfaceAvailableForRequestListeners.get(ifaceType);
if (listeners.size() == 0) {
return;
}
boolean isAvailable = isItPossibleToCreateIface(chipInfos, ifaceType);
if (VDBG) {
Log.d(TAG, "Interface available for: ifaceType=" + ifaceType + " = " + isAvailable);
}
for (Map.Entry<InterfaceAvailableForRequestListenerProxy, Boolean> listenerEntry :
listeners.entrySet()) {
if (listenerEntry.getValue() == null || listenerEntry.getValue() != isAvailable) {
if (VDBG) {
Log.d(TAG, "Interface available listener dispatched: ifaceType=" + ifaceType
+ ", listener=" + listenerEntry.getKey());
}
listenerEntry.getKey().triggerWithArg(isAvailable);
}
listenerEntry.setValue(isAvailable);
}
}
}
另外就是在有接口创建或者摧毁的时候按优先级进行轮询通知,p2p算优先级比较低
// dispatch all available for request listeners of the specified type AND clean-out the list:
// listeners are called once at most!
private boolean dispatchAvailableForRequestListeners() {
if (VDBG) Log.d(TAG, "dispatchAvailableForRequestListeners");
synchronized (mLock) {
WifiChipInfo[] chipInfos = getAllChipInfo();
if (chipInfos == null) {
Log.e(TAG, "dispatchAvailableForRequestListeners: no chip info found");
stopWifi(); // major error: shutting down
return false;
}
if (VDBG) {
Log.d(TAG, "dispatchAvailableForRequestListeners: chipInfos="
+ Arrays.deepToString(chipInfos));
}
for (int ifaceType : IFACE_TYPES_BY_PRIORITY) {
dispatchAvailableForRequestListenersForType(ifaceType, chipInfos);
}
}
return true;
}
/* This "PRIORITY" is not for deciding interface elimination (that is controlled by
* allowedToDeleteIfaceTypeForRequestedType. This priority is used for:
* - Comparing 2 configuration options
* - Order of dispatch of available for request listeners
*/
private static final int[] IFACE_TYPES_BY_PRIORITY =
{IfaceType.AP, IfaceType.STA, IfaceType.P2P, IfaceType.NAN};
创建
private IWifiIface createIface(int ifaceType, boolean lowPriority,
InterfaceDestroyedListener destroyedListener, Handler handler) {
if (mDbg) {
Log.d(TAG, "createIface: ifaceType=" + ifaceType + ", lowPriority=" + lowPriority);
}
synchronized (mLock) {
WifiChipInfo[] chipInfos = getAllChipInfo();
if (chipInfos == null) {
Log.e(TAG, "createIface: no chip info found");
stopWifi(); // major error: shutting down
return null;
}
if (!validateInterfaceCache(chipInfos)) {
Log.e(TAG, "createIface: local cache is invalid!");
stopWifi(); // major error: shutting down
return null;
}
IWifiIface iface = createIfaceIfPossible(chipInfos, ifaceType, lowPriority,
destroyedListener, handler);
if (iface != null) { // means that some configuration has changed
if (!dispatchAvailableForRequestListeners()) {
return null; // catastrophic failure - shut down
}
}
return iface;
}
}
摧毁
/**
* Removes (releases/destroys) the given interface. Will trigger any registered
* InterfaceDestroyedListeners and possibly some InterfaceAvailableForRequestListeners if we
* can potentially create some other interfaces as a result of removing this interface.
*/
public boolean removeIface(IWifiIface iface) {
boolean success = removeIfaceInternal(iface);
dispatchAvailableForRequestListeners();
return success;
}
3.总结
i加加 发布了192 篇原创文章 · 获赞 56 · 访问量 15万+ 私信 关注
标签:零一,listener,两百,handler,P2P,p2p0,interface,TAG,ifaceType 来源: https://blog.csdn.net/sinat_20059415/article/details/104072149