summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Shuibing Dai <shuibing@google.com> 2023-11-21 13:59:29 -0800
committer Shuibing Dai <shuibing@google.com> 2024-02-14 23:54:09 +0000
commitd183a0e3aeeb3be3ce48ba9e8c6a8082c3243345 (patch)
tree331b5afc7de83c037bddfdb406dc34f7113304f2
parent97d66af67bb39fc688186240c03f6ef5597360ff (diff)
Add new p2p listener APIs
Bug: 312521671 Test: atest WifiP2pServiveImplTest Change-Id: I44029c0b4b95a747530dfec59735ce51e7132e02
-rw-r--r--framework/aidl-export/android/net/wifi/p2p/WifiP2pGroupList.aidl19
-rw-r--r--framework/api/current.txt18
-rw-r--r--framework/api/system-current.txt4
-rw-r--r--framework/java/android/net/wifi/p2p/IWifiP2pListener.aidl45
-rw-r--r--framework/java/android/net/wifi/p2p/IWifiP2pManager.aidl4
-rw-r--r--framework/java/android/net/wifi/p2p/WifiP2pManager.java315
-rw-r--r--framework/tests/src/android/net/wifi/p2p/WifiP2pManagerTest.java14
-rw-r--r--service/java/com/android/server/wifi/p2p/WifiP2pServiceImpl.java240
-rw-r--r--service/tests/wifitests/src/com/android/server/wifi/p2p/WifiP2pServiceImplTest.java109
9 files changed, 756 insertions, 12 deletions
diff --git a/framework/aidl-export/android/net/wifi/p2p/WifiP2pGroupList.aidl b/framework/aidl-export/android/net/wifi/p2p/WifiP2pGroupList.aidl
new file mode 100644
index 0000000000..eb52254a5a
--- /dev/null
+++ b/framework/aidl-export/android/net/wifi/p2p/WifiP2pGroupList.aidl
@@ -0,0 +1,19 @@
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi.p2p;
+
+parcelable WifiP2pGroupList;
diff --git a/framework/api/current.txt b/framework/api/current.txt
index 8f0efa2ffe..ab684fd3f9 100644
--- a/framework/api/current.txt
+++ b/framework/api/current.txt
@@ -1382,6 +1382,7 @@ package android.net.wifi.p2p {
method public boolean isGroupClientRemovalSupported();
method public boolean isGroupOwnerIPv6LinkLocalAddressProvided();
method public boolean isSetVendorElementsSupported();
+ method @FlaggedApi("com.android.wifi.flags.android_v_wifi_api") @RequiresPermission(allOf={android.Manifest.permission.NEARBY_WIFI_DEVICES, android.Manifest.permission.ACCESS_WIFI_STATE}, conditional=true) public void registerWifiP2pListener(@NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.p2p.WifiP2pManager.WifiP2pListener);
method public void removeClient(@NonNull android.net.wifi.p2p.WifiP2pManager.Channel, @NonNull android.net.MacAddress, @Nullable android.net.wifi.p2p.WifiP2pManager.ActionListener);
method @RequiresPermission(android.Manifest.permission.MANAGE_WIFI_NETWORK_SELECTION) public void removeExternalApprover(@NonNull android.net.wifi.p2p.WifiP2pManager.Channel, @NonNull android.net.MacAddress, @Nullable android.net.wifi.p2p.WifiP2pManager.ActionListener);
method public void removeGroup(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.WifiP2pManager.ActionListener);
@@ -1404,6 +1405,7 @@ package android.net.wifi.p2p {
method @RequiresPermission(allOf={android.Manifest.permission.NEARBY_WIFI_DEVICES, android.Manifest.permission.ACCESS_FINE_LOCATION}, conditional=true) public void startListening(@NonNull android.net.wifi.p2p.WifiP2pManager.Channel, @Nullable android.net.wifi.p2p.WifiP2pManager.ActionListener);
method public void stopListening(@NonNull android.net.wifi.p2p.WifiP2pManager.Channel, @Nullable android.net.wifi.p2p.WifiP2pManager.ActionListener);
method public void stopPeerDiscovery(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.WifiP2pManager.ActionListener);
+ method @FlaggedApi("com.android.wifi.flags.android_v_wifi_api") public void unregisterWifiP2pListener(@NonNull android.net.wifi.p2p.WifiP2pManager.WifiP2pListener);
field public static final String ACTION_WIFI_P2P_LISTEN_STATE_CHANGED = "android.net.wifi.p2p.action.WIFI_P2P_LISTEN_STATE_CHANGED";
field public static final String ACTION_WIFI_P2P_REQUEST_RESPONSE_CHANGED = "android.net.wifi.p2p.action.WIFI_P2P_REQUEST_RESPONSE_CHANGED";
field public static final int BUSY = 2; // 0x2
@@ -1511,6 +1513,22 @@ package android.net.wifi.p2p {
method public void onUpnpServiceAvailable(java.util.List<java.lang.String>, android.net.wifi.p2p.WifiP2pDevice);
}
+ @FlaggedApi("com.android.wifi.flags.android_v_wifi_api") public static interface WifiP2pManager.WifiP2pListener {
+ method @FlaggedApi("com.android.wifi.flags.android_v_wifi_api") public default void onDeviceConfigurationChanged(@Nullable android.net.wifi.p2p.WifiP2pDevice);
+ method @FlaggedApi("com.android.wifi.flags.android_v_wifi_api") public default void onDiscoveryStateChanged(boolean);
+ method @FlaggedApi("com.android.wifi.flags.android_v_wifi_api") public default void onFrequencyChanged(@NonNull android.net.wifi.p2p.WifiP2pInfo, @NonNull android.net.wifi.p2p.WifiP2pGroup);
+ method @FlaggedApi("com.android.wifi.flags.android_v_wifi_api") public default void onGroupCreated(@NonNull android.net.wifi.p2p.WifiP2pInfo, @NonNull android.net.wifi.p2p.WifiP2pGroup);
+ method @FlaggedApi("com.android.wifi.flags.android_v_wifi_api") public default void onGroupCreating();
+ method @FlaggedApi("com.android.wifi.flags.android_v_wifi_api") public default void onGroupCreationFailed();
+ method @FlaggedApi("com.android.wifi.flags.android_v_wifi_api") public default void onGroupNegotiationRejectedByUser();
+ method @FlaggedApi("com.android.wifi.flags.android_v_wifi_api") public default void onGroupRemoved();
+ method @FlaggedApi("com.android.wifi.flags.android_v_wifi_api") public default void onListenStateChanged(boolean);
+ method @FlaggedApi("com.android.wifi.flags.android_v_wifi_api") public default void onPeerClientDisconnected(@NonNull android.net.wifi.p2p.WifiP2pInfo, @NonNull android.net.wifi.p2p.WifiP2pGroup);
+ method @FlaggedApi("com.android.wifi.flags.android_v_wifi_api") public default void onPeerClientJoined(@NonNull android.net.wifi.p2p.WifiP2pInfo, @NonNull android.net.wifi.p2p.WifiP2pGroup);
+ method @FlaggedApi("com.android.wifi.flags.android_v_wifi_api") public default void onPeerListChanged(@NonNull android.net.wifi.p2p.WifiP2pDeviceList);
+ method @FlaggedApi("com.android.wifi.flags.android_v_wifi_api") public default void onStateChanged(boolean);
+ }
+
public final class WifiP2pWfdInfo implements android.os.Parcelable {
ctor public WifiP2pWfdInfo();
ctor public WifiP2pWfdInfo(@Nullable android.net.wifi.p2p.WifiP2pWfdInfo);
diff --git a/framework/api/system-current.txt b/framework/api/system-current.txt
index 21fbe6f461..d645f7d494 100644
--- a/framework/api/system-current.txt
+++ b/framework/api/system-current.txt
@@ -1643,6 +1643,10 @@ package android.net.wifi.p2p {
method public void onPersistentGroupInfoAvailable(@NonNull android.net.wifi.p2p.WifiP2pGroupList);
}
+ @FlaggedApi("com.android.wifi.flags.android_v_wifi_api") public static interface WifiP2pManager.WifiP2pListener {
+ method @FlaggedApi("com.android.wifi.flags.android_v_wifi_api") public default void onPersistentGroupsChanged(@NonNull android.net.wifi.p2p.WifiP2pGroupList);
+ }
+
}
package android.net.wifi.rtt {
diff --git a/framework/java/android/net/wifi/p2p/IWifiP2pListener.aidl b/framework/java/android/net/wifi/p2p/IWifiP2pListener.aidl
new file mode 100644
index 0000000000..4f9467101e
--- /dev/null
+++ b/framework/java/android/net/wifi/p2p/IWifiP2pListener.aidl
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi.p2p;
+
+import android.net.wifi.p2p.WifiP2pDevice;
+import android.net.wifi.p2p.WifiP2pDeviceList;
+import android.net.wifi.p2p.WifiP2pInfo;
+import android.net.wifi.p2p.WifiP2pGroup;
+import android.net.wifi.p2p.WifiP2pGroupList;
+
+/**
+ * Interface for Wi-Fi p2p listener.
+ * @hide
+ */
+oneway interface IWifiP2pListener
+{
+ void onStateChanged(boolean p2pEnabled);
+ void onDiscoveryStateChanged(boolean started);
+ void onListenStateChanged(boolean started);
+ void onDeviceConfigurationChanged(in WifiP2pDevice p2pDevice);
+ void onPeerListChanged(in WifiP2pDeviceList p2pDeviceList);
+ void onPersistentGroupsChanged(in WifiP2pGroupList p2pGroupList);
+ void onGroupCreating();
+ void onGroupNegotiationRejectedByUser();
+ void onGroupCreationFailed();
+ void onGroupCreated(in WifiP2pInfo p2pInfo, in WifiP2pGroup p2pGroup);
+ void onPeerClientJoined(in WifiP2pInfo p2pInfo, in WifiP2pGroup p2pGroup);
+ void onPeerClientDisconnected(in WifiP2pInfo p2pInfo, in WifiP2pGroup p2pGroup);
+ void onFrequencyChanged(in WifiP2pInfo p2pInfo, in WifiP2pGroup p2pGroup);
+ void onGroupRemoved();
+}
diff --git a/framework/java/android/net/wifi/p2p/IWifiP2pManager.aidl b/framework/java/android/net/wifi/p2p/IWifiP2pManager.aidl
index f29a9b3c3a..088ead4927 100644
--- a/framework/java/android/net/wifi/p2p/IWifiP2pManager.aidl
+++ b/framework/java/android/net/wifi/p2p/IWifiP2pManager.aidl
@@ -16,6 +16,8 @@
package android.net.wifi.p2p;
+import android.net.wifi.p2p.IWifiP2pListener;
+
import android.os.Bundle;
import android.os.Messenger;
@@ -32,5 +34,7 @@ interface IWifiP2pManager
void setMiracastMode(int mode);
void checkConfigureWifiDisplayPermission();
long getSupportedFeatures();
+ void registerWifiP2pListener(in IWifiP2pListener listener, in String packageName, in Bundle extras);
+ void unregisterWifiP2pListener(in IWifiP2pListener listener);
}
diff --git a/framework/java/android/net/wifi/p2p/WifiP2pManager.java b/framework/java/android/net/wifi/p2p/WifiP2pManager.java
index 4129a5bd84..3600f74b14 100644
--- a/framework/java/android/net/wifi/p2p/WifiP2pManager.java
+++ b/framework/java/android/net/wifi/p2p/WifiP2pManager.java
@@ -51,6 +51,7 @@ import android.os.RemoteException;
import android.text.TextUtils;
import android.util.CloseGuard;
import android.util.Log;
+import android.util.SparseArray;
import android.view.Display;
import androidx.annotation.RequiresApi;
@@ -588,6 +589,8 @@ public class WifiP2pManager {
*/
private static final int WIFI_P2P_VENDOR_ELEMENTS_MAXIMUM_LENGTH = 512;
+ private Context mContext;
+
IWifiP2pManager mService;
private static final int BASE = Protocol.BASE_WIFI_P2P_MANAGER;
@@ -861,6 +864,7 @@ public class WifiP2pManager {
/** @hide */
public static final int RESPONSE_GET_LISTEN_STATE = BASE + 118;
+ private static final SparseArray<IWifiP2pListener> sWifiP2pListenerMap = new SparseArray<>();
/**
* Create a new WifiP2pManager instance. Applications use
* {@link android.content.Context#getSystemService Context.getSystemService()} to retrieve
@@ -1247,6 +1251,316 @@ public class WifiP2pManager {
void onPinGenerated(@NonNull MacAddress deviceAddress, @NonNull String pin);
}
+ /**
+ * Interface used to listen to Wi-Fi p2p various changes such as device state change,
+ * discovery started/stopped, connection change, etc.
+ */
+ @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
+ public interface WifiP2pListener {
+ /**
+ * Called when Wi-Fi p2p has been enabled or disabled.
+ * @see #WIFI_P2P_STATE_CHANGED_ACTION
+ * @see #requestP2pState(Channel, P2pStateListener)
+ *
+ * @param p2pEnabled indicates whether Wi-Fi p2p is enabled or disabled.
+ */
+ @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
+ default void onStateChanged(boolean p2pEnabled) {
+ }
+
+ /**
+ * Called when peer discovery has either started or stopped.
+ * @see #WIFI_P2P_DISCOVERY_CHANGED_ACTION
+ * @see #requestDiscoveryState(Channel, DiscoveryStateListener)
+ *
+ * @param started indicates whether discovery has started or stopped.
+ */
+ @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
+ default void onDiscoveryStateChanged(boolean started) {
+ }
+
+ /**
+ * Called when peer listen has either started or stopped.
+ * @see #ACTION_WIFI_P2P_LISTEN_STATE_CHANGED
+ * @see #getListenState(Channel, Executor, Consumer)
+ *
+ * @param started indicates whether listen has started or stopped.
+ */
+ @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
+ default void onListenStateChanged(boolean started) {
+ }
+
+ /**
+ * Called when this device details have changed.
+ * @see #WIFI_P2P_THIS_DEVICE_CHANGED_ACTION
+ * @see #requestDeviceInfo(Channel, DeviceInfoListener)
+ *
+ * @param p2pDevice provides this device details.
+ */
+ @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
+ default void onDeviceConfigurationChanged(@Nullable WifiP2pDevice p2pDevice) {
+ }
+
+ /**
+ * Called when the available peer list has changed. This can be sent as a result of peers
+ * being found, lost or updated.
+ * @see #WIFI_P2P_PEERS_CHANGED_ACTION
+ * @see #requestPeers(Channel, PeerListListener)
+ *
+ * @param p2pDeviceList provides the full list of current peers.
+ */
+ @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
+ default void onPeerListChanged(@NonNull WifiP2pDeviceList p2pDeviceList) {
+ }
+
+ /**
+ * Called when remembered persistent groups have changed.
+ * @see #ACTION_WIFI_P2P_PERSISTENT_GROUPS_CHANGED
+ * @see #requestPersistentGroupInfo(Channel, PersistentGroupInfoListener)
+ *
+ * @param p2pGroupList provides the full list of p2p group.
+ *
+ * @hide
+ */
+ @SystemApi
+ @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
+ default void onPersistentGroupsChanged(@NonNull WifiP2pGroupList p2pGroupList) {
+ }
+
+ /**
+ * Called when either group owner or group client is creating p2p group.
+ */
+ @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
+ default void onGroupCreating() {
+ }
+
+ /**
+ * Called when group negotiation has been rejected by user.
+ */
+ @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
+ default void onGroupNegotiationRejectedByUser() {
+ }
+
+ /**
+ * Called when group creation has failed.
+ */
+ @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
+ default void onGroupCreationFailed() {
+ }
+
+ /**
+ * Called when either group owner or group client has created p2p group successfully.
+ *
+ * @param p2pInfo provides the p2p connection info.
+ * @param p2pGroup provides the details of the group.
+ */
+ @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
+ default void onGroupCreated(@NonNull WifiP2pInfo p2pInfo,
+ @NonNull WifiP2pGroup p2pGroup) {
+ }
+
+ /**
+ * Called to indicate group owner that a group client has joined p2p group successfully.
+ *
+ * @param p2pInfo provides the p2p connection info.
+ * @param p2pGroup provides the details of the group.
+ */
+ @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
+ default void onPeerClientJoined(@NonNull WifiP2pInfo p2pInfo,
+ @NonNull WifiP2pGroup p2pGroup) {
+ }
+
+ /**
+ * Called to indicate group owner that a group client has disconnected.
+ *
+ * @param p2pInfo provides the p2p connection info.
+ * @param p2pGroup provides the details of the group.
+ */
+ @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
+ default void onPeerClientDisconnected(@NonNull WifiP2pInfo p2pInfo,
+ @NonNull WifiP2pGroup p2pGroup) {
+ }
+
+ /**
+ * Called when the frequency of a formed group has been changed.
+ *
+ * @param p2pInfo provides the p2p connection info.
+ * @param p2pGroup provides the details of the group.
+ */
+ @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
+ default void onFrequencyChanged(@NonNull WifiP2pInfo p2pInfo,
+ @NonNull WifiP2pGroup p2pGroup) {
+ }
+
+ /**
+ * Called when p2p group has been removed.
+ */
+ @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
+ default void onGroupRemoved() {
+ }
+ }
+
+ /**
+ * Helper class to support wifi p2p listener.
+ */
+ private static class OnWifiP2pListenerProxy extends IWifiP2pListener.Stub {
+ @NonNull
+ private Executor mExecutor;
+ @NonNull
+ private WifiP2pListener mListener;
+
+ OnWifiP2pListenerProxy(@NonNull Executor executor,
+ @NonNull WifiP2pListener listener) {
+ Objects.requireNonNull(executor);
+ Objects.requireNonNull(listener);
+ mExecutor = executor;
+ mListener = listener;
+ }
+
+ @Override
+ public void onStateChanged(boolean p2pEnabled) {
+ Binder.clearCallingIdentity();
+ mExecutor.execute(() -> mListener.onStateChanged(p2pEnabled));
+ }
+
+ @Override
+ public void onDiscoveryStateChanged(boolean started) {
+ Binder.clearCallingIdentity();
+ mExecutor.execute(() -> mListener.onDiscoveryStateChanged(started));
+ }
+
+ @Override
+ public void onListenStateChanged(boolean started) {
+ Binder.clearCallingIdentity();
+ mExecutor.execute(() -> mListener.onListenStateChanged(started));
+ }
+
+ @Override
+ public void onDeviceConfigurationChanged(WifiP2pDevice p2pDevice) {
+ Binder.clearCallingIdentity();
+ mExecutor.execute(() -> mListener.onDeviceConfigurationChanged(p2pDevice));
+ }
+
+ @Override
+ public void onPeerListChanged(WifiP2pDeviceList p2pDeviceList) {
+ Binder.clearCallingIdentity();
+ mExecutor.execute(() -> mListener.onPeerListChanged(p2pDeviceList));
+ }
+
+ @Override
+ public void onPersistentGroupsChanged(WifiP2pGroupList p2pGroupList) {
+ Binder.clearCallingIdentity();
+ mExecutor.execute(() -> mListener.onPersistentGroupsChanged(p2pGroupList));
+ }
+
+ @Override
+ public void onGroupCreating() {
+ Binder.clearCallingIdentity();
+ mExecutor.execute(() -> mListener.onGroupCreating());
+ }
+
+ @Override
+ public void onGroupNegotiationRejectedByUser() {
+ Binder.clearCallingIdentity();
+ mExecutor.execute(() -> mListener.onGroupNegotiationRejectedByUser());
+ }
+
+ @Override
+ public void onGroupCreationFailed() {
+ Binder.clearCallingIdentity();
+ mExecutor.execute(() -> mListener.onGroupCreationFailed());
+ }
+
+ @Override
+ public void onGroupCreated(WifiP2pInfo p2pInfo, WifiP2pGroup p2pGroup) {
+ Binder.clearCallingIdentity();
+ mExecutor.execute(() -> mListener.onGroupCreated(p2pInfo, p2pGroup));
+ }
+
+ @Override
+ public void onPeerClientJoined(WifiP2pInfo p2pInfo, WifiP2pGroup p2pGroup) {
+ Binder.clearCallingIdentity();
+ mExecutor.execute(() -> mListener.onPeerClientJoined(p2pInfo, p2pGroup));
+ }
+
+ @Override
+ public void onPeerClientDisconnected(WifiP2pInfo p2pInfo, WifiP2pGroup p2pGroup) {
+ Binder.clearCallingIdentity();
+ mExecutor.execute(() -> mListener.onPeerClientDisconnected(p2pInfo, p2pGroup));
+ }
+
+ @Override
+ public void onFrequencyChanged(WifiP2pInfo p2pInfo, WifiP2pGroup p2pGroup) {
+ Binder.clearCallingIdentity();
+ mExecutor.execute(() -> mListener.onFrequencyChanged(p2pInfo, p2pGroup));
+ }
+
+ @Override
+ public void onGroupRemoved() {
+ Binder.clearCallingIdentity();
+ mExecutor.execute(() -> mListener.onGroupRemoved());
+ }
+ }
+
+ /**
+ * Add a listener to listen to Wi-Fi p2p various changes.
+ *
+ * @param executor the Executor on which to execute the callbacks.
+ * @param listener listener for the Wi-Fi p2p connection changes.
+ * @throws SecurityException if the caller is missing required permissions.
+ * @throws IllegalArgumentException if incorrect input arguments are provided.
+ */
+ @RequiresPermission(allOf = {
+ android.Manifest.permission.NEARBY_WIFI_DEVICES,
+ android.Manifest.permission.ACCESS_WIFI_STATE
+ }, conditional = true)
+ @RequiresApi(Build.VERSION_CODES.TIRAMISU)
+ @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
+ public void registerWifiP2pListener(@NonNull @CallbackExecutor Executor executor,
+ @NonNull WifiP2pListener listener) {
+ Log.d(TAG, "registerWifiP2pListener: listener=" + listener + ", executor=" + executor);
+ final int listenerIdentifier = System.identityHashCode(listener);
+ synchronized (sWifiP2pListenerMap) {
+ try {
+ IWifiP2pListener.Stub listenerProxy = new OnWifiP2pListenerProxy(executor,
+ listener);
+ sWifiP2pListenerMap.put(listenerIdentifier, listenerProxy);
+ Bundle extras = prepareExtrasBundleWithAttributionSource(mContext);
+ mService.registerWifiP2pListener(listenerProxy, mContext.getOpPackageName(),
+ extras);
+ } catch (RemoteException e) {
+ sWifiP2pListenerMap.remove(listenerIdentifier);
+ throw e.rethrowFromSystemServer();
+ }
+ }
+ }
+
+ /**
+ * Remove a listener added using
+ * {@link #registerWifiP2pListener(Executor, WifiP2pListener)}
+ *
+ * @param listener the listener to be removed.
+ * @throws IllegalArgumentException if incorrect input arguments are provided.
+ */
+ @RequiresApi(Build.VERSION_CODES.TIRAMISU)
+ @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
+ public void unregisterWifiP2pListener(@NonNull WifiP2pListener listener) {
+ Log.d(TAG, "unregisterWifiP2pListener: listener=" + listener);
+ final int listenerIdentifier = System.identityHashCode(listener);
+ synchronized (sWifiP2pListenerMap) {
+ try {
+ if (!sWifiP2pListenerMap.contains(listenerIdentifier)) {
+ Log.w(TAG, "Unknown external listener " + listenerIdentifier);
+ return;
+ }
+ mService.unregisterWifiP2pListener(sWifiP2pListenerMap.get(listenerIdentifier));
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ } finally {
+ sWifiP2pListenerMap.remove(listenerIdentifier);
+ }
+ }
+ }
/**
* A channel that connects the application to the Wifi p2p framework.
@@ -1646,6 +1960,7 @@ public class WifiP2pManager {
extras.putInt(EXTRA_PARAM_KEY_DISPLAY_ID, displayId);
Channel channel = initializeChannel(srcContext, srcLooper, listener,
getMessenger(binder, srcContext.getOpPackageName(), extras), binder);
+ mContext = srcContext;
return channel;
}
diff --git a/framework/tests/src/android/net/wifi/p2p/WifiP2pManagerTest.java b/framework/tests/src/android/net/wifi/p2p/WifiP2pManagerTest.java
index 15116ebb47..21c42d8760 100644
--- a/framework/tests/src/android/net/wifi/p2p/WifiP2pManagerTest.java
+++ b/framework/tests/src/android/net/wifi/p2p/WifiP2pManagerTest.java
@@ -34,6 +34,7 @@ import static org.mockito.Mockito.when;
import android.content.AttributionSource;
import android.content.Context;
import android.net.wifi.ScanResult;
+import android.net.wifi.SynchronousExecutor;
import android.os.Bundle;
import android.os.test.TestLooper;
import android.view.Display;
@@ -267,4 +268,17 @@ public class WifiP2pManagerTest {
WifiP2pManager.FEATURE_GROUP_OWNER_IPV6_LINK_LOCAL_ADDRESS_PROVIDED);
assertTrue(mDut.isGroupOwnerIPv6LinkLocalAddressProvided());
}
+
+ @Test
+ public void testWifiP2pListener() throws Exception {
+ assumeTrue(SdkLevel.isAtLeastT());
+ SynchronousExecutor executor = mock(SynchronousExecutor.class);
+ WifiP2pManager.WifiP2pListener listener = mock(WifiP2pManager.WifiP2pListener.class);
+ mDut.initialize(mContextMock, mTestLooper.getLooper(), null);
+ mDut.registerWifiP2pListener(executor, listener);
+ verify(mP2pServiceMock).registerWifiP2pListener(any(IWifiP2pListener.Stub.class),
+ eq(PACKAGE_NAME), any(Bundle.class));
+ mDut.unregisterWifiP2pListener(listener);
+ verify(mP2pServiceMock).unregisterWifiP2pListener(any(IWifiP2pListener.Stub.class));
+ }
}
diff --git a/service/java/com/android/server/wifi/p2p/WifiP2pServiceImpl.java b/service/java/com/android/server/wifi/p2p/WifiP2pServiceImpl.java
index d8439f7152..f82807e486 100644
--- a/service/java/com/android/server/wifi/p2p/WifiP2pServiceImpl.java
+++ b/service/java/com/android/server/wifi/p2p/WifiP2pServiceImpl.java
@@ -65,6 +65,7 @@ import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.net.wifi.WpsInfo;
+import android.net.wifi.p2p.IWifiP2pListener;
import android.net.wifi.p2p.IWifiP2pManager;
import android.net.wifi.p2p.WifiP2pConfig;
import android.net.wifi.p2p.WifiP2pDevice;
@@ -93,6 +94,7 @@ import android.os.Message;
import android.os.Messenger;
import android.os.ParcelFileDescriptor;
import android.os.Process;
+import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.UserHandle;
@@ -172,6 +174,7 @@ import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.Executor;
import java.util.stream.Collectors;
/**
@@ -458,6 +461,9 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub {
@VisibleForTesting
static final String GO_EAPOL_IP_RANGE_DEFAULT_END_ADDRESS = "192.168.49.254";
+ private final RemoteCallbackList<IWifiP2pListener> mWifiP2pListeners =
+ new RemoteCallbackList<>();
+
/**
* Error code definition.
* see the Table.8 in the WiFi Direct specification for the detail.
@@ -1094,6 +1100,208 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub {
return mWifiNative.getSupportedFeatures();
}
+ /**
+ * See {@link WifiP2pManager#registerWifiP2pListener(Executor, WifiP2pManager.WifiP2pListener)}
+ */
+ @Override
+ @RequiresApi(Build.VERSION_CODES.TIRAMISU)
+ public void registerWifiP2pListener(IWifiP2pListener listener, String packageName,
+ Bundle extras) {
+ if (!SdkLevel.isAtLeastT()) {
+ throw new UnsupportedOperationException();
+ }
+ if (listener == null) {
+ throw new IllegalArgumentException("listener should not be null");
+ }
+ mWifiPermissionsUtil.enforceNearbyDevicesPermission(
+ extras.getParcelable(WifiManager.EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE), false,
+ TAG + " registerWifiP2pListener");
+ Log.i(TAG, "registerWifiP2pListener uid=" + Binder.getCallingUid());
+ mWifiP2pListeners.register(listener);
+ }
+
+ /**
+ * See {@link WifiP2pManager#unregisterWifiP2pListener(WifiP2pManager.WifiP2pListener)}
+ */
+ @Override
+ @RequiresApi(Build.VERSION_CODES.TIRAMISU)
+ public void unregisterWifiP2pListener(IWifiP2pListener listener) {
+ if (listener == null) {
+ throw new IllegalArgumentException("listener must not be null");
+ }
+ Log.i(TAG, "unregisterWifiP2pListener uid=" + Binder.getCallingUid());
+ mWifiP2pListeners.unregister(listener);
+ }
+
+ private void onStateChanged(boolean p2pEnabled) {
+ int numCallbacks = mWifiP2pListeners.beginBroadcast();
+ for (int i = 0; i < numCallbacks; i++) {
+ try {
+ mWifiP2pListeners.getBroadcastItem(i).onStateChanged(p2pEnabled);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failure calling onStateChanged" + e);
+ }
+ }
+ mWifiP2pListeners.finishBroadcast();
+ }
+
+ private void onDiscoveryStateChanged(boolean started) {
+ int numCallbacks = mWifiP2pListeners.beginBroadcast();
+ for (int i = 0; i < numCallbacks; i++) {
+ try {
+ mWifiP2pListeners.getBroadcastItem(i).onDiscoveryStateChanged(started);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failure calling onDiscoveryStateChanged" + e);
+ }
+ }
+ mWifiP2pListeners.finishBroadcast();
+ }
+
+ private void onListenStateChanged(boolean started) {
+ int numCallbacks = mWifiP2pListeners.beginBroadcast();
+ for (int i = 0; i < numCallbacks; i++) {
+ try {
+ mWifiP2pListeners.getBroadcastItem(i).onListenStateChanged(started);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failure calling onListenStateChanged" + e);
+ }
+ }
+ mWifiP2pListeners.finishBroadcast();
+ }
+
+ private void onDeviceConfigurationChanged(WifiP2pDevice p2pDevice) {
+ int numCallbacks = mWifiP2pListeners.beginBroadcast();
+ for (int i = 0; i < numCallbacks; i++) {
+ try {
+ mWifiP2pListeners.getBroadcastItem(i).onDeviceConfigurationChanged(p2pDevice);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failure calling onDeviceConfigurationChanged" + e);
+ }
+ }
+ mWifiP2pListeners.finishBroadcast();
+ }
+
+ private void onPeerListChanged(WifiP2pDeviceList p2pDeviceList) {
+ int numCallbacks = mWifiP2pListeners.beginBroadcast();
+ for (int i = 0; i < numCallbacks; i++) {
+ try {
+ mWifiP2pListeners.getBroadcastItem(i).onPeerListChanged(p2pDeviceList);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failure calling onPeerListChanged" + e);
+ }
+ }
+ mWifiP2pListeners.finishBroadcast();
+ }
+
+ private void onPersistentGroupsChanged(WifiP2pGroupList p2pGroupList) {
+ int numCallbacks = mWifiP2pListeners.beginBroadcast();
+ for (int i = 0; i < numCallbacks; i++) {
+ try {
+ mWifiP2pListeners.getBroadcastItem(i).onPersistentGroupsChanged(p2pGroupList);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failure calling onPersistentGroupsChanged" + e);
+ }
+ }
+ mWifiP2pListeners.finishBroadcast();
+ }
+
+ private void onGroupCreating() {
+ int numCallbacks = mWifiP2pListeners.beginBroadcast();
+ for (int i = 0; i < numCallbacks; i++) {
+ try {
+ mWifiP2pListeners.getBroadcastItem(i).onGroupCreating();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failure calling onGroupCreating" + e);
+ }
+ }
+ mWifiP2pListeners.finishBroadcast();
+ }
+
+ private void onGroupNegotiationRejectedByUser() {
+ int numCallbacks = mWifiP2pListeners.beginBroadcast();
+ for (int i = 0; i < numCallbacks; i++) {
+ try {
+ mWifiP2pListeners.getBroadcastItem(i).onGroupNegotiationRejectedByUser();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failure calling onGroupNegotiationRejectedByUser" + e);
+ }
+ }
+ mWifiP2pListeners.finishBroadcast();
+ }
+
+ private void onGroupCreationFailed() {
+ int numCallbacks = mWifiP2pListeners.beginBroadcast();
+ for (int i = 0; i < numCallbacks; i++) {
+ try {
+ mWifiP2pListeners.getBroadcastItem(i).onGroupCreationFailed();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failure calling onGroupCreationFailed" + e);
+ }
+ }
+ mWifiP2pListeners.finishBroadcast();
+ }
+
+ private void onGroupCreated(WifiP2pInfo p2pInfo, WifiP2pGroup p2pGroup) {
+ int numCallbacks = mWifiP2pListeners.beginBroadcast();
+ for (int i = 0; i < numCallbacks; i++) {
+ try {
+ mWifiP2pListeners.getBroadcastItem(i).onGroupCreated(p2pInfo, p2pGroup);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failure calling onGroupCreated" + e);
+ }
+ }
+ mWifiP2pListeners.finishBroadcast();
+ }
+
+ private void onPeerClientJoined(WifiP2pInfo p2pInfo, WifiP2pGroup p2pGroup) {
+ int numCallbacks = mWifiP2pListeners.beginBroadcast();
+ for (int i = 0; i < numCallbacks; i++) {
+ try {
+ mWifiP2pListeners.getBroadcastItem(i).onPeerClientJoined(p2pInfo, p2pGroup);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failure calling onPeerClientJoined" + e);
+ }
+ }
+ mWifiP2pListeners.finishBroadcast();
+ }
+
+ private void onPeerClientDisconnected(WifiP2pInfo p2pInfo, WifiP2pGroup p2pGroup) {
+ int numCallbacks = mWifiP2pListeners.beginBroadcast();
+ for (int i = 0; i < numCallbacks; i++) {
+ try {
+ mWifiP2pListeners.getBroadcastItem(i).onPeerClientDisconnected(p2pInfo,
+ p2pGroup);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failure calling onPeerClientDisconnected" + e);
+ }
+ }
+ mWifiP2pListeners.finishBroadcast();
+ }
+
+ private void onFrequencyChanged(WifiP2pInfo p2pInfo, WifiP2pGroup p2pGroup) {
+ int numCallbacks = mWifiP2pListeners.beginBroadcast();
+ for (int i = 0; i < numCallbacks; i++) {
+ try {
+ mWifiP2pListeners.getBroadcastItem(i).onFrequencyChanged(p2pInfo, p2pGroup);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failure calling onFrequencyChanged" + e);
+ }
+ }
+ mWifiP2pListeners.finishBroadcast();
+ }
+
+ private void onGroupRemoved() {
+ int numCallbacks = mWifiP2pListeners.beginBroadcast();
+ for (int i = 0; i < numCallbacks; i++) {
+ try {
+ mWifiP2pListeners.getBroadcastItem(i).onGroupRemoved();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failure calling onGroupRemoved" + e);
+ }
+ }
+ mWifiP2pListeners.finishBroadcast();
+ }
+
private boolean getWfdPermission(int uid) {
WifiPermissionsWrapper wifiPermissionsWrapper = mWifiInjector.getWifiPermissionsWrapper();
return wifiPermissionsWrapper.getUidPermission(
@@ -3879,6 +4087,7 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub {
public void enterImpl() {
logSmStateName(this.getName(),
getCurrentState() != null ? getCurrentState().getName() : "");
+ onGroupCreating();
if (SdkLevel.isAtLeastT()) {
mDetailedState = NetworkInfo.DetailedState.CONNECTING;
sendP2pConnectionChangedBroadcast();
@@ -4057,6 +4266,7 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub {
int delay = sendP2pRejection();
mDetailedState = NetworkInfo.DetailedState.DISCONNECTED;
+ onGroupNegotiationRejectedByUser();
sendP2pConnectionChangedBroadcast();
mSavedPeerConfig.invalidate();
transitionTo(mP2pRejectWaitState);
@@ -4780,6 +4990,7 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub {
// In case of a negotiation group, connection changed is sent
// after a client joins. For autonomous, send now
if (mAutonomousGroup) {
+ onGroupCreated(new WifiP2pInfo(mWifiP2pInfo), eraseOwnDeviceAddress(mGroup));
sendP2pConnectionChangedBroadcast();
}
@@ -4824,6 +5035,8 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub {
} else {
loge("Connect on null device address, ignore");
}
+ onPeerClientJoined(new WifiP2pInfo(mWifiP2pInfo),
+ eraseOwnDeviceAddress(mGroup));
sendP2pConnectionChangedBroadcast();
break;
}
@@ -4846,6 +5059,8 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub {
// We end up sending connection changed broadcast
// when this happens at exit()
} else {
+ onPeerClientDisconnected(new WifiP2pInfo(mWifiP2pInfo),
+ eraseOwnDeviceAddress(mGroup));
// Notify when a client disconnects from group
sendP2pConnectionChangedBroadcast();
}
@@ -4935,6 +5150,8 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub {
} catch (Exception e) {
loge("Failed to add iface to local network " + e);
}
+ onGroupCreated(new WifiP2pInfo(mWifiP2pInfo),
+ eraseOwnDeviceAddress(mGroup));
sendP2pConnectionChangedBroadcast();
break;
case IPC_PROVISIONING_SUCCESS:
@@ -4959,6 +5176,8 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub {
byte[] goInterfaceMacAddress = mGroup.interfaceAddress;
if (goInterfaceMacAddress == null) {
setWifiP2pInfoOnGroupFormationWithInetAddress(null);
+ onGroupCreated(new WifiP2pInfo(mWifiP2pInfo),
+ eraseOwnDeviceAddress(mGroup));
sendP2pConnectionChangedBroadcast();
break;
}
@@ -4969,6 +5188,8 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub {
InetAddress goIp = Inet6Address.getByAddress(null, goIpv6Address,
NetworkInterface.getByName(mGroup.getInterface()));
setWifiP2pInfoOnGroupFormationWithInetAddress(goIp);
+ onGroupCreated(new WifiP2pInfo(mWifiP2pInfo),
+ eraseOwnDeviceAddress(mGroup));
sendP2pConnectionChangedBroadcast();
} catch (UnknownHostException | SocketException e) {
loge("Unable to retrieve link-local IPv6 address of group owner "
@@ -5195,6 +5416,8 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub {
case WifiP2pMonitor.P2P_FREQUENCY_CHANGED_EVENT:
if (mGroup != null) {
mGroup.setFrequency(message.arg1);
+ onFrequencyChanged(new WifiP2pInfo(mWifiP2pInfo),
+ eraseOwnDeviceAddress(mGroup));
sendP2pConnectionChangedBroadcast();
}
break;
@@ -5245,6 +5468,7 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub {
updateThisDevice(WifiP2pDevice.AVAILABLE);
resetWifiP2pInfo();
mDetailedState = NetworkInfo.DetailedState.DISCONNECTED;
+ onGroupRemoved();
sendP2pConnectionChangedBroadcast();
if (!SdkLevel.isAtLeastU()) {
// Ensure tethering service to stop tethering.
@@ -5428,6 +5652,7 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub {
}
private void sendP2pStateChangedBroadcast(boolean enabled) {
+ onStateChanged(enabled);
final Intent intent = new Intent(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
if (enabled) {
@@ -5445,6 +5670,7 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub {
mDiscoveryStarted = started;
if (mVerboseLoggingEnabled) logd("discovery change broadcast " + started);
+ onDiscoveryStateChanged(started);
final Intent intent = new Intent(WifiP2pManager.WIFI_P2P_DISCOVERY_CHANGED_ACTION);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
@@ -5459,6 +5685,7 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub {
mListenStarted = started;
if (mVerboseLoggingEnabled) logd("wifi p2p listen change broadcast " + started);
+ onListenStateChanged(started);
final Intent intent = new Intent(WifiP2pManager.ACTION_WIFI_P2P_LISTEN_STATE_CHANGED);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
@@ -5516,16 +5743,21 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub {
}
private void sendThisDeviceChangedBroadcast() {
+ WifiP2pDevice p2pDevice = eraseOwnDeviceAddress(mThisDevice);
+ onDeviceConfigurationChanged(p2pDevice);
+
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,
- eraseOwnDeviceAddress(mThisDevice));
+ intent.putExtra(WifiP2pManager.EXTRA_WIFI_P2P_DEVICE, p2pDevice);
sendBroadcastWithExcludedPermissions(intent, null);
}
private void sendPeersChangedBroadcast() {
+ WifiP2pDeviceList p2pDeviceList = new WifiP2pDeviceList(mPeers);
+ onPeerListChanged(p2pDeviceList);
+
final Intent intent = new Intent(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION);
- intent.putExtra(WifiP2pManager.EXTRA_P2P_DEVICE_LIST, new WifiP2pDeviceList(mPeers));
+ intent.putExtra(WifiP2pManager.EXTRA_P2P_DEVICE_LIST, p2pDeviceList);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
sendBroadcastWithExcludedPermissions(intent, null);
}
@@ -5671,6 +5903,7 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub {
}
private void sendP2pPersistentGroupsChangedBroadcast() {
+ onPersistentGroupsChanged(new WifiP2pGroupList(mGroups, null));
if (mVerboseLoggingEnabled) logd("sending p2p persistent groups changed broadcast");
Intent intent = new Intent(WifiP2pManager.ACTION_WIFI_P2P_PERSISTENT_GROUPS_CHANGED);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
@@ -6702,6 +6935,7 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub {
}
resetWifiP2pInfo();
mDetailedState = NetworkInfo.DetailedState.FAILED;
+ onGroupCreationFailed();
sendP2pConnectionChangedBroadcast();
// Remove only the peer we failed to connect to so that other devices discovered
diff --git a/service/tests/wifitests/src/com/android/server/wifi/p2p/WifiP2pServiceImplTest.java b/service/tests/wifitests/src/com/android/server/wifi/p2p/WifiP2pServiceImplTest.java
index 49ea05c2fa..e04f92fd84 100644
--- a/service/tests/wifitests/src/com/android/server/wifi/p2p/WifiP2pServiceImplTest.java
+++ b/service/tests/wifitests/src/com/android/server/wifi/p2p/WifiP2pServiceImplTest.java
@@ -94,6 +94,7 @@ import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.net.wifi.WifiScanner;
import android.net.wifi.WpsInfo;
+import android.net.wifi.p2p.IWifiP2pListener;
import android.net.wifi.p2p.WifiP2pConfig;
import android.net.wifi.p2p.WifiP2pDevice;
import android.net.wifi.p2p.WifiP2pDeviceList;
@@ -111,10 +112,12 @@ import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
+import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.PersistableBundle;
import android.os.Process;
+import android.os.RemoteException;
import android.os.UserHandle;
import android.os.UserManager;
import android.os.WorkSource;
@@ -199,6 +202,7 @@ public class WifiP2pServiceImplTest extends WifiBaseTest {
private static final String thisDeviceName = "thisDeviceName";
private static final String ANONYMIZED_DEVICE_ADDRESS = "02:00:00:00:00:00";
private static final String TEST_PACKAGE_NAME = "com.p2p.test";
+ private static final String TEST_NETWORK_NAME = "DIRECT-xy-NEW";
private static final String TEST_ANDROID_ID = "314Deadbeef";
private static final String[] TEST_REQUIRED_PERMISSIONS_T =
new String[] {
@@ -246,6 +250,8 @@ public class WifiP2pServiceImplTest extends WifiBaseTest {
private ArgumentCaptor<TetheringManager.TetheringEventCallback> mTetheringEventCallbackCaptor =
ArgumentCaptor.forClass(TetheringManager.TetheringEventCallback.class);
private TetheringManager.TetheringEventCallback mTetheringEventCallback;
+ private Bundle mExtras = new Bundle();
+ private IWifiP2pListener mP2pListener = mock(IWifiP2pListener.class);
private ArgumentCaptor<WifiSettingsConfigStore.OnSettingsChangedListener>
mD2DAllowedSettingsCallbackCaptor =
ArgumentCaptor.forClass(WifiSettingsConfigStore.OnSettingsChangedListener.class);
@@ -327,7 +333,7 @@ public class WifiP2pServiceImplTest extends WifiBaseTest {
// for general group started event
mTestWifiP2pNewPersistentGoGroup = new WifiP2pGroup();
mTestWifiP2pNewPersistentGoGroup.setNetworkId(WifiP2pGroup.NETWORK_ID_PERSISTENT);
- mTestWifiP2pNewPersistentGoGroup.setNetworkName("DIRECT-xy-NEW");
+ mTestWifiP2pNewPersistentGoGroup.setNetworkName(TEST_NETWORK_NAME);
mTestWifiP2pNewPersistentGoGroup.setOwner(new WifiP2pDevice(thisDeviceMac));
mTestWifiP2pNewPersistentGoGroup.setIsGroupOwner(true);
mTestWifiP2pNewPersistentGoGroup.setInterface(IFACE_NAME_P2P);
@@ -1272,7 +1278,7 @@ public class WifiP2pServiceImplTest extends WifiBaseTest {
/**
* Check the broadcast of WIFI_P2P_THIS_DEVICE_CHANGED_ACTION is sent as expected.
*/
- private void checkSendThisDeviceChangedBroadcast() {
+ private void checkSendThisDeviceChangedBroadcast() throws RemoteException {
ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
String[] permission_gold;
if (mWifiPermissionsUtil.isLocationModeEnabled()) {
@@ -1314,6 +1320,9 @@ public class WifiP2pServiceImplTest extends WifiBaseTest {
}
verifyDeviceChangedBroadcastIntent(intentCaptor.getValue());
}
+ if (SdkLevel.isAtLeastT()) {
+ verify(mP2pListener, atLeastOnce()).onDeviceConfigurationChanged(any());
+ }
}
/**
@@ -1507,6 +1516,7 @@ public class WifiP2pServiceImplTest extends WifiBaseTest {
when(mWifiInjector.getWifiHandlerLocalLog()).thenReturn(mLocalLog);
when(mDeviceConfigFacade.isP2pFailureBugreportEnabled()).thenReturn(false);
when(mContext.getSystemService(TetheringManager.class)).thenReturn(mTetheringManager);
+ when(mP2pListener.asBinder()).thenReturn(mock(IBinder.class));
mWifiP2pServiceImpl = new WifiP2pServiceImpl(mContext, mWifiInjector);
if (supported) {
@@ -1567,6 +1577,9 @@ public class WifiP2pServiceImplTest extends WifiBaseTest {
mClient2 = new Binder();
when(mContext.createContextAsUser(any(), anyInt())).thenReturn(mContext);
mWifiP2pServiceImpl.handleBootCompleted();
+ if (SdkLevel.isAtLeastT()) {
+ mWifiP2pServiceImpl.registerWifiP2pListener(mP2pListener, TEST_PACKAGE_NAME, mExtras);
+ }
}
@After
@@ -1619,7 +1632,7 @@ public class WifiP2pServiceImplTest extends WifiBaseTest {
forceP2pEnabled(mClient1);
WifiP2pGroup group = new WifiP2pGroup();
group.setNetworkId(WifiP2pGroup.NETWORK_ID_PERSISTENT);
- group.setNetworkName("DIRECT-xy-NEW");
+ group.setNetworkName(TEST_NETWORK_NAME);
group.setOwner(new WifiP2pDevice("thisDeviceMac"));
group.setIsGroupOwner(true);
group.setInterface(IFACE_NAME_P2P);
@@ -1773,6 +1786,9 @@ public class WifiP2pServiceImplTest extends WifiBaseTest {
inOrder.verify(mContext).sendStickyBroadcastAsUser(argThat(
new WifiP2pServiceImplTest.P2pStateChangedIntentMatcher(
WifiP2pManager.WIFI_P2P_STATE_ENABLED)), any());
+ if (SdkLevel.isAtLeastT()) {
+ verify(mP2pListener).onStateChanged(eq(true));
+ }
// disabled broadcast sent when user restriction is set
simulateUserRestrictionChange(true);
@@ -1780,6 +1796,9 @@ public class WifiP2pServiceImplTest extends WifiBaseTest {
inOrder.verify(mContext).sendStickyBroadcastAsUser(argThat(
new WifiP2pServiceImplTest.P2pStateChangedIntentMatcher(
WifiP2pManager.WIFI_P2P_STATE_DISABLED)), any());
+ if (SdkLevel.isAtLeastT()) {
+ verify(mP2pListener).onStateChanged(eq(false));
+ }
// no disabled broadcast sent when Wi-Fi is disabled since broadcast already sent
simulateWifiStateChange(false);
@@ -2248,6 +2267,9 @@ public class WifiP2pServiceImplTest extends WifiBaseTest {
assertTrue(mClientHandler.hasMessages(WifiP2pManager.DISCOVER_PEERS_SUCCEEDED));
verify(mLastCallerInfoManager).put(eq(WifiManager.API_P2P_DISCOVER_PEERS), anyInt(),
anyInt(), anyInt(), anyString(), eq(true));
+ if (SdkLevel.isAtLeastT()) {
+ verify(mP2pListener).onDiscoveryStateChanged(eq(true));
+ }
}
/**
@@ -2813,6 +2835,9 @@ public class WifiP2pServiceImplTest extends WifiBaseTest {
verify(mWifiPermissionsUtil).checkCanAccessWifiDirect(eq(TEST_PACKAGE_NAME),
eq("testFeature"), anyInt(), eq(true));
}
+ if (SdkLevel.isAtLeastT()) {
+ verify(mP2pListener).onListenStateChanged(eq(true));
+ }
}
/**
@@ -3416,7 +3441,7 @@ public class WifiP2pServiceImplTest extends WifiBaseTest {
WifiP2pGroup group = new WifiP2pGroup();
group.setNetworkId(WifiP2pGroup.NETWORK_ID_PERSISTENT);
- group.setNetworkName("DIRECT-xy-NEW");
+ group.setNetworkName(TEST_NETWORK_NAME);
group.setOwner(new WifiP2pDevice("thisDeviceMac"));
group.setIsGroupOwner(true);
group.setInterface(IFACE_NAME_P2P);
@@ -3722,7 +3747,7 @@ public class WifiP2pServiceImplTest extends WifiBaseTest {
WifiP2pServiceImpl.P2pStatus.NO_COMMON_CHANNEL);
WifiP2pGroup group = new WifiP2pGroup();
group.setNetworkId(WifiP2pGroup.NETWORK_ID_PERSISTENT);
- group.setNetworkName("DIRECT-xy-NEW");
+ group.setNetworkName(TEST_NETWORK_NAME);
group.setOwner(new WifiP2pDevice("thisDeviceMac"));
group.setIsGroupOwner(true);
group.setInterface(IFACE_NAME_P2P);
@@ -5323,6 +5348,9 @@ public class WifiP2pServiceImplTest extends WifiBaseTest {
when(mWifiNative.p2pListNetworks(any())).thenReturn(true);
sendSimpleMsg(mClientMessenger, WifiP2pManager.FACTORY_RESET);
checkSendP2pPersistentGroupsChangedBroadcast();
+ if (SdkLevel.isAtLeastT()) {
+ verify(mP2pListener, atLeastOnce()).onPersistentGroupsChanged(any());
+ }
verify(mWifiInjector).getUserManager();
verify(mPackageManager).getNameForUid(anyInt());
verify(mWifiPermissionsUtil).checkNetworkSettingsPermission(anyInt());
@@ -6476,7 +6504,7 @@ public class WifiP2pServiceImplTest extends WifiBaseTest {
WifiP2pGroup group = new WifiP2pGroup();
group.setNetworkId(WifiP2pGroup.NETWORK_ID_PERSISTENT);
- group.setNetworkName("DIRECT-xy-NEW");
+ group.setNetworkName(TEST_NETWORK_NAME);
group.setOwner(new WifiP2pDevice("thisDeviceMac"));
group.setIsGroupOwner(true);
group.setInterface(IFACE_NAME_P2P);
@@ -6659,7 +6687,7 @@ public class WifiP2pServiceImplTest extends WifiBaseTest {
forceP2pEnabled(mClient1);
WifiP2pGroup group = new WifiP2pGroup();
group.setNetworkId(WifiP2pGroup.NETWORK_ID_PERSISTENT);
- group.setNetworkName("DIRECT-xy-NEW");
+ group.setNetworkName(TEST_NETWORK_NAME);
group.setOwner(new WifiP2pDevice("thisDeviceMac"));
group.setIsGroupOwner(true);
group.setInterface(IFACE_NAME_P2P);
@@ -7437,7 +7465,9 @@ public class WifiP2pServiceImplTest extends WifiBaseTest {
WifiP2pMonitor.PROV_DISC_STATUS_REJECTED,
pdEvent);
verify(mWifiNative).p2pCancelConnect();
-
+ if (SdkLevel.isAtLeastT()) {
+ verify(mP2pListener).onGroupCreationFailed();
+ }
}
/**
@@ -7468,6 +7498,9 @@ public class WifiP2pServiceImplTest extends WifiBaseTest {
sendSimpleMsg(null, WifiP2pServiceImpl.PEER_CONNECTION_USER_REJECT);
verify(mWifiNative).p2pReject(eq(mTestWifiP2pDevice.deviceAddress));
+ if (SdkLevel.isAtLeastT()) {
+ verify(mP2pListener).onGroupNegotiationRejectedByUser();
+ }
}
/**
@@ -7695,7 +7728,7 @@ public class WifiP2pServiceImplTest extends WifiBaseTest {
forceP2pEnabled(mClient1);
WifiP2pGroup group = new WifiP2pGroup();
group.setNetworkId(WifiP2pGroup.NETWORK_ID_PERSISTENT);
- group.setNetworkName("DIRECT-xy-NEW");
+ group.setNetworkName(TEST_NETWORK_NAME);
group.setOwner(new WifiP2pDevice("thisDeviceMac"));
group.setIsGroupOwner(true);
group.setInterface(IFACE_NAME_P2P);
@@ -8037,6 +8070,64 @@ public class WifiP2pServiceImplTest extends WifiBaseTest {
new WorkSource(mClient1.getCallingUid(), TEST_PACKAGE_NAME));
}
+ @Test
+ public void testWifiP2pListener() throws Exception {
+ assumeTrue(SdkLevel.isAtLeastT());
+ forceP2pEnabled(mClient1);
+ when(mWifiNative.p2pGroupAdd(any(), eq(false))).thenReturn(true);
+ WifiP2pGroup p2pGroup = new WifiP2pGroup();
+ p2pGroup.setNetworkId(WifiP2pGroup.NETWORK_ID_PERSISTENT);
+ p2pGroup.setNetworkName(TEST_NETWORK_NAME);
+ p2pGroup.setOwner(new WifiP2pDevice("thisDeviceMac"));
+ p2pGroup.setIsGroupOwner(true);
+ p2pGroup.setInterface(IFACE_NAME_P2P);
+
+ sendCreateGroupMsgWithConfigValidAsGroup(mClientMessenger);
+ sendGroupStartedMsg(p2pGroup);
+ simulateTetherReady();
+ verify(mP2pListener).onGroupCreating();
+ ArgumentCaptor<WifiP2pInfo> p2pInfoCaptor = ArgumentCaptor.forClass(WifiP2pInfo.class);
+ ArgumentCaptor<WifiP2pGroup> p2pGroupCaptor = ArgumentCaptor.forClass(WifiP2pGroup.class);
+ verify(mP2pListener).onGroupCreated(p2pInfoCaptor.capture(), p2pGroupCaptor.capture());
+ assertEquals(TEST_NETWORK_NAME, p2pGroupCaptor.getValue().getNetworkName());
+ assertTrue(p2pGroupCaptor.getValue().isClientListEmpty());
+ assertTrue(p2pInfoCaptor.getValue().groupFormed);
+
+ WifiP2pDevice peerClientDevice = new WifiP2pDevice();
+ peerClientDevice.deviceName = "peerClientDeviceName";
+ peerClientDevice.deviceAddress = "11:22:33:aa:bb:cc";
+ peerClientDevice.setInterfaceMacAddress(MacAddress.fromString(PEER_INTERFACE_ADDRESS));
+ sendSimpleMsg(null, WifiP2pMonitor.AP_STA_CONNECTED_EVENT, peerClientDevice);
+ verify(mP2pListener).onPeerClientJoined(p2pInfoCaptor.capture(),
+ p2pGroupCaptor.capture());
+ assertFalse(p2pGroupCaptor.getValue().isClientListEmpty());
+ assertTrue(p2pInfoCaptor.getValue().groupFormed);
+
+ sendSimpleMsg(null, WifiP2pMonitor.AP_STA_DISCONNECTED_EVENT, peerClientDevice);
+ verify(mP2pListener).onPeerClientDisconnected(p2pInfoCaptor.capture(),
+ p2pGroupCaptor.capture());
+ assertTrue(p2pGroupCaptor.getValue().isClientListEmpty());
+ assertTrue(p2pInfoCaptor.getValue().groupFormed);
+ verify(mP2pListener, atLeastOnce()).onPeerListChanged(any());
+
+ sendSimpleMsg(null, WifiP2pMonitor.P2P_FREQUENCY_CHANGED_EVENT, TEST_GROUP_FREQUENCY);
+ verify(mP2pListener).onFrequencyChanged(p2pInfoCaptor.capture(),
+ p2pGroupCaptor.capture());
+ assertEquals(TEST_GROUP_FREQUENCY, p2pGroupCaptor.getValue().getFrequency());
+
+ sendGroupRemovedMsg();
+ mockEnterDisabledState();
+ mLooper.dispatchAll();
+ verify(mP2pListener).onGroupRemoved();
+
+ mWifiP2pServiceImpl.unregisterWifiP2pListener(mP2pListener);
+ doThrow(new SecurityException()).when(mWifiPermissionsUtil).enforceNearbyDevicesPermission(
+ any(), anyBoolean(), any());
+ assertThrows(SecurityException.class,
+ () -> mWifiP2pServiceImpl.registerWifiP2pListener(mP2pListener, TEST_PACKAGE_NAME,
+ mExtras));
+ }
+
/**
* Verify that p2p disable when the D2d allowed value changes to false
*/