230 lines
9.3 KiB
Java
230 lines
9.3 KiB
Java
/*
|
|
* 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 com.google.snippet.wifi.direct;
|
|
|
|
import android.content.BroadcastReceiver;
|
|
import android.content.Context;
|
|
import android.content.Intent;
|
|
import android.content.IntentFilter;
|
|
import android.net.NetworkInfo;
|
|
import android.net.wifi.WifiManager;
|
|
import android.net.wifi.p2p.WifiP2pConfig;
|
|
import android.net.wifi.p2p.WifiP2pDevice;
|
|
import android.net.wifi.p2p.WifiP2pGroup;
|
|
import android.net.wifi.p2p.WifiP2pInfo;
|
|
import android.net.wifi.p2p.WifiP2pManager;
|
|
import android.os.Build;
|
|
import android.util.Log;
|
|
|
|
import androidx.test.platform.app.InstrumentationRegistry;
|
|
|
|
import com.android.compatibility.common.util.ApiLevelUtil;
|
|
import com.android.compatibility.common.util.PollingCheck;
|
|
import com.android.compatibility.common.util.ShellIdentityUtils;
|
|
|
|
import com.google.android.mobly.snippet.Snippet;
|
|
import com.google.android.mobly.snippet.rpc.Rpc;
|
|
|
|
import org.json.JSONException;
|
|
|
|
public class WifiDirectSnippet implements Snippet {
|
|
|
|
private static final String TAG = "WifiDirectSnippet";
|
|
private final Context mContext;
|
|
|
|
private final WifiP2pManager mP2pManager;
|
|
private WifiP2pInfo mP2pInfo;
|
|
private WifiP2pGroup mP2pGroup;
|
|
private WifiP2pManager.Channel mChannel;
|
|
private WifiManager mWifiManager;
|
|
|
|
private final Object mLock = new Object();
|
|
|
|
private final WifiP2pManager.ChannelListener mChannelListener =
|
|
new WifiP2pManager.ChannelListener() {
|
|
public void onChannelDisconnected() {
|
|
Log.e(TAG, "P2P channel disconnected");
|
|
}
|
|
};
|
|
|
|
private BroadcastReceiver mP2pStateChangedReceiver =
|
|
new BroadcastReceiver() {
|
|
@Override
|
|
public void onReceive(Context c, Intent intent) {
|
|
String action = intent.getAction();
|
|
if (action.equals(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION)) {
|
|
Log.d(TAG, "Wifi P2p State Changed.");
|
|
int state = intent.getIntExtra(WifiP2pManager.EXTRA_WIFI_STATE, 0);
|
|
if (state == WifiP2pManager.WIFI_P2P_STATE_DISABLED) {
|
|
Log.d(TAG, "Disabled");
|
|
} else if (state == WifiP2pManager.WIFI_P2P_STATE_ENABLED) {
|
|
Log.d(TAG, "Enabled");
|
|
}
|
|
} else if (action.equals(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION)) {
|
|
Log.d(TAG, "Wifi P2p Peers Changed");
|
|
} else if (action.equals(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION)) {
|
|
Log.d(TAG, "Wifi P2p Connection Changed.");
|
|
synchronized (mLock) {
|
|
NetworkInfo networkInfo = intent
|
|
.getParcelableExtra(WifiP2pManager.EXTRA_NETWORK_INFO);
|
|
if (networkInfo.isConnected()) {
|
|
Log.d(TAG, "Wifi P2p Connected.");
|
|
mP2pInfo = intent.getParcelableExtra(WifiP2pManager.EXTRA_WIFI_P2P_INFO);
|
|
mP2pGroup = intent.getParcelableExtra(WifiP2pManager.EXTRA_WIFI_P2P_GROUP);
|
|
mLock.notify();
|
|
} else if (networkInfo.isConnectedOrConnecting()) {
|
|
Log.d(TAG, "Wifi P2p is in connecting state");
|
|
} else {
|
|
Log.d(TAG, "Wifi P2p is in disconnected state");
|
|
}
|
|
}
|
|
} else if (action.equals(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION)) {
|
|
Log.d(TAG, "Wifi P2p This Device Changed.");
|
|
WifiP2pDevice device = intent
|
|
.getParcelableExtra(WifiP2pManager.EXTRA_WIFI_P2P_DEVICE);
|
|
} else if (action.equals(WifiP2pManager.WIFI_P2P_DISCOVERY_CHANGED_ACTION)) {
|
|
Log.d(TAG, "Wifi P2p Discovery Changed.");
|
|
int state = intent.getIntExtra(WifiP2pManager.EXTRA_DISCOVERY_STATE, 0);
|
|
if (state == WifiP2pManager.WIFI_P2P_DISCOVERY_STARTED) {
|
|
Log.d(TAG, "discovery started.");
|
|
} else if (state == WifiP2pManager.WIFI_P2P_DISCOVERY_STOPPED) {
|
|
Log.d(TAG, "discovery stopped.");
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
class WifiP2pActionListener implements WifiP2pManager.ActionListener {
|
|
private final String mOperation;
|
|
WifiP2pActionListener(String action) {
|
|
mOperation = action;
|
|
}
|
|
|
|
@Override
|
|
public void onSuccess() {
|
|
Log.d(TAG, mOperation + " OnSuccess");
|
|
}
|
|
@Override
|
|
public void onFailure(int reason) {
|
|
Log.d(TAG, mOperation + " onFailure - reason: " + reason);
|
|
}
|
|
}
|
|
|
|
private WifiP2pConfig buildWifiP2pConfig(String networkName, String passphrase,
|
|
int frequency) {
|
|
WifiP2pConfig.Builder builder = new WifiP2pConfig.Builder();
|
|
builder.setNetworkName(networkName);
|
|
builder.setPassphrase(passphrase);
|
|
if (frequency != 0) {
|
|
builder.setGroupOperatingFrequency(frequency);
|
|
}
|
|
return builder.build();
|
|
}
|
|
|
|
public WifiDirectSnippet() {
|
|
mContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
|
|
mP2pManager = mContext.getSystemService(WifiP2pManager.class);
|
|
mWifiManager = mContext.getSystemService(WifiManager.class);
|
|
|
|
Log.d(TAG, "WifiDirectSnippet - init");
|
|
}
|
|
|
|
@Rpc(description = "Check if Aware pairing supported")
|
|
public boolean isChannelConstrainedDiscoverySupported()
|
|
throws InterruptedException {
|
|
if (!ApiLevelUtil.isAtLeast(Build.VERSION_CODES.TIRAMISU)) {
|
|
return false;
|
|
}
|
|
return mP2pManager.isChannelConstrainedDiscoverySupported();
|
|
}
|
|
|
|
@Rpc(description = "Execute p2p initialize")
|
|
public void initializeP2p() throws Exception {
|
|
ShellIdentityUtils.invokeWithShellPermissions(
|
|
() -> mWifiManager.allowAutojoinGlobal(false));
|
|
ShellIdentityUtils.invokeWithShellPermissions(() -> mWifiManager.disconnect());
|
|
PollingCheck.check(
|
|
"Wifi not disconnected",
|
|
20000,
|
|
() -> mWifiManager.getConnectionInfo().getNetworkId() == -1);
|
|
mChannel = mP2pManager.initialize(mContext, mContext.getMainLooper(), mChannelListener);
|
|
IntentFilter intentFilter = new IntentFilter(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION);
|
|
intentFilter.addAction(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION);
|
|
intentFilter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);
|
|
intentFilter.addAction(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION);
|
|
intentFilter.setPriority(999);
|
|
mContext.registerReceiver(mP2pStateChangedReceiver, intentFilter);
|
|
Log.d(TAG, "Wifi Direct initialization completed");
|
|
}
|
|
|
|
@Rpc(description = "Close P2P channel")
|
|
public void closeP2p() throws JSONException {
|
|
if (mChannel != null) {
|
|
mChannel.close();
|
|
mChannel = null;
|
|
Log.d(TAG, "Wifi Direct close called");
|
|
}
|
|
ShellIdentityUtils.invokeWithShellPermissions(() -> mWifiManager.allowAutojoinGlobal(true));
|
|
Log.d(TAG, "Wifi Direct close completed");
|
|
}
|
|
|
|
@Rpc(description = "Create a P2P group owner with config")
|
|
public boolean p2pCreateGroup(String networkName, String passphrase,
|
|
int frequency) throws JSONException {
|
|
if (mChannel == null) {
|
|
Log.d(TAG, "p2pCreateGroup failed -should call initializeP2p first ");
|
|
return false;
|
|
}
|
|
WifiP2pConfig wifiP2pConfig = buildWifiP2pConfig(networkName, passphrase, frequency);
|
|
mP2pManager.createGroup(mChannel, wifiP2pConfig,
|
|
new WifiP2pActionListener("CreateGroup"));
|
|
Log.d(TAG, "p2pCreateGroup succeeded");
|
|
return true;
|
|
}
|
|
|
|
@Rpc(description = "Connect to a P2P group owner with config")
|
|
public long p2pConnect(String networkName, String passphrase,
|
|
int frequency) throws JSONException, InterruptedException {
|
|
if (mChannel == null) {
|
|
Log.d(TAG, "p2pConnect failed- should call initializeP2p first");
|
|
return -1;
|
|
}
|
|
WifiP2pConfig wifiP2pConfig = buildWifiP2pConfig(networkName, passphrase, frequency);
|
|
long startTime = System.currentTimeMillis();
|
|
mP2pManager.connect(mChannel, wifiP2pConfig,
|
|
new WifiP2pActionListener("Connect"));
|
|
|
|
synchronized (mLock) {
|
|
mLock.wait(5000);
|
|
}
|
|
|
|
if (mP2pInfo == null || !mP2pInfo.groupFormed || mP2pGroup == null) {
|
|
Log.d(TAG, "p2pConnect failure");
|
|
|
|
return -1;
|
|
}
|
|
|
|
Log.d(TAG, "p2pConnect succeeded - group not null");
|
|
return System.currentTimeMillis() - startTime;
|
|
}
|
|
|
|
@Override
|
|
public void shutdown() {
|
|
Log.d(TAG, "Wifi Direct shutdown called");
|
|
}
|
|
}
|