blob: 45daf850963828c980ac9cb4ced94b3e244e9a9d [file] [log] [blame]
/*
* Copyright (C) 2017 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.android.bips.p2p;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.net.wifi.p2p.WifiP2pDevice;
import android.net.wifi.p2p.WifiP2pDeviceList;
import android.net.wifi.p2p.WifiP2pManager;
import android.os.Looper;
import android.util.Log;
import com.android.bips.BuiltInPrintService;
import com.android.bips.util.BroadcastMonitor;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.regex.Pattern;
/**
* Manage the process of discovering P2P printer devices
*/
class P2pDiscoveryProcedure {
private static final String TAG = P2pDiscoveryProcedure.class.getSimpleName();
private static final boolean DEBUG = false;
private static final Pattern PRINTER_PATTERN =
Pattern.compile("^(^3-.+-[145])|(0003.+000[145])$");
private final WifiP2pManager mP2pManager;
private final List<P2pPeerListener> mListeners = new CopyOnWriteArrayList<>();
private final List<WifiP2pDevice> mPeers = new ArrayList<>();
private BroadcastMonitor mBroadcastMonitor;
private WifiP2pManager.Channel mChannel;
P2pDiscoveryProcedure(BuiltInPrintService service, WifiP2pManager p2pManager,
P2pPeerListener listener) {
mP2pManager = p2pManager;
if (DEBUG) Log.d(TAG, "P2pDiscoveryProcedure()");
mChannel = mP2pManager.initialize(service, Looper.getMainLooper(), null);
mListeners.add(listener);
BroadcastReceiver receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION.equals(action)) {
int state = intent.getIntExtra(WifiP2pManager.EXTRA_WIFI_STATE, -1);
boolean isP2pEnabled = state == WifiP2pManager.WIFI_P2P_STATE_ENABLED;
if (DEBUG) Log.d(TAG, "WIFI_P2P_STATE_CHANGED_ACTION: enabled=" + isP2pEnabled);
if (isP2pEnabled) {
mP2pManager.stopPeerDiscovery(mChannel, null);
mP2pManager.discoverPeers(mChannel, null);
}
} else if (WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION.equals(action)) {
WifiP2pDeviceList list = intent.getParcelableExtra(
WifiP2pManager.EXTRA_P2P_DEVICE_LIST);
Collection<WifiP2pDevice> newPeers = list.getDeviceList();
updatePeers(newPeers);
if (newPeers.isEmpty()) {
// Remind system we are still interested
mP2pManager.stopPeerDiscovery(mChannel, null);
mP2pManager.discoverPeers(mChannel, null);
}
}
}
};
mBroadcastMonitor = service.receiveBroadcasts(receiver,
WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION,
WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION);
mP2pManager.discoverPeers(mChannel, null);
}
void addListener(P2pPeerListener listener) {
mListeners.add(listener);
if (!mPeers.isEmpty()) {
for (WifiP2pDevice peer : mPeers) {
listener.onPeerFound(peer);
}
}
}
void removeListener(P2pPeerListener listener) {
mListeners.remove(listener);
}
List<P2pPeerListener> getListeners() {
return mListeners;
}
/**
* Signal find/loss of each device to listeners as it occurs
*/
private void updatePeers(Collection<WifiP2pDevice> newPeers) {
List<WifiP2pDevice> oldPeers = new ArrayList<>(mPeers);
// Reset peer list and populate with new printer-type devices
mPeers.clear();
for (WifiP2pDevice peer : newPeers) {
if (PRINTER_PATTERN.matcher(peer.primaryDeviceType).find()) {
mPeers.add(peer);
}
}
// Notify newly found devices
Set<String> foundAddresses = new HashSet<>();
for (WifiP2pDevice peer : mPeers) {
foundAddresses.add(peer.deviceAddress);
WifiP2pDevice old = getDevice(oldPeers, peer.deviceAddress);
if (old == null || !old.equals(peer)) {
for (P2pPeerListener listener : mListeners) {
listener.onPeerFound(peer);
}
}
}
// Notify lost devices
for (WifiP2pDevice oldPeer : oldPeers) {
if (!foundAddresses.contains(oldPeer.deviceAddress)) {
for (P2pPeerListener listener : mListeners) {
listener.onPeerLost(oldPeer);
}
}
}
}
private WifiP2pDevice getDevice(Collection<WifiP2pDevice> peers, String address) {
for (WifiP2pDevice found : peers) {
if (found.deviceAddress.equals(address)) {
return found;
}
}
return null;
}
/** Stop the discovery procedure */
public void cancel() {
if (DEBUG) Log.d(TAG, "stop()");
mBroadcastMonitor.close();
if (mChannel != null) {
mP2pManager.stopPeerDiscovery(mChannel, null);
mChannel.close();
mChannel = null;
}
}
}