• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.bips.p2p;
18 
19 import android.content.BroadcastReceiver;
20 import android.content.Context;
21 import android.content.Intent;
22 import android.net.wifi.p2p.WifiP2pDevice;
23 import android.net.wifi.p2p.WifiP2pDeviceList;
24 import android.net.wifi.p2p.WifiP2pManager;
25 import android.os.Looper;
26 import android.util.Log;
27 
28 import com.android.bips.BuiltInPrintService;
29 import com.android.bips.util.BroadcastMonitor;
30 
31 import java.util.ArrayList;
32 import java.util.Collection;
33 import java.util.HashSet;
34 import java.util.List;
35 import java.util.Set;
36 import java.util.concurrent.CopyOnWriteArrayList;
37 import java.util.regex.Pattern;
38 
39 /**
40  * Manage the process of discovering P2P printer devices
41  */
42 class P2pDiscoveryProcedure {
43     private static final String TAG = P2pDiscoveryProcedure.class.getSimpleName();
44     private static final boolean DEBUG = false;
45 
46     private static final Pattern PRINTER_PATTERN =
47             Pattern.compile("^(^3-.+-[145])|(0003.+000[145])$");
48 
49     private final WifiP2pManager mP2pManager;
50     private final List<P2pPeerListener> mListeners = new CopyOnWriteArrayList<>();
51     private final List<WifiP2pDevice> mPeers = new ArrayList<>();
52     private BroadcastMonitor mBroadcastMonitor;
53     private WifiP2pManager.Channel mChannel;
54 
P2pDiscoveryProcedure(BuiltInPrintService service, WifiP2pManager p2pManager, P2pPeerListener listener)55     P2pDiscoveryProcedure(BuiltInPrintService service, WifiP2pManager p2pManager,
56             P2pPeerListener listener) {
57         mP2pManager = p2pManager;
58         if (DEBUG) Log.d(TAG, "P2pDiscoveryProcedure()");
59         mChannel = mP2pManager.initialize(service, Looper.getMainLooper(), null);
60         mListeners.add(listener);
61 
62         BroadcastReceiver receiver = new BroadcastReceiver() {
63             @Override
64             public void onReceive(Context context, Intent intent) {
65                 String action = intent.getAction();
66                 if (WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION.equals(action)) {
67                     int state = intent.getIntExtra(WifiP2pManager.EXTRA_WIFI_STATE, -1);
68                     boolean isP2pEnabled = state == WifiP2pManager.WIFI_P2P_STATE_ENABLED;
69                     if (DEBUG) Log.d(TAG, "WIFI_P2P_STATE_CHANGED_ACTION: enabled=" + isP2pEnabled);
70                     if (isP2pEnabled) {
71                         mP2pManager.stopPeerDiscovery(mChannel, null);
72                         mP2pManager.discoverPeers(mChannel, null);
73                     }
74                 } else if (WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION.equals(action)) {
75                     WifiP2pDeviceList list = intent.getParcelableExtra(
76                             WifiP2pManager.EXTRA_P2P_DEVICE_LIST);
77                     Collection<WifiP2pDevice> newPeers = list.getDeviceList();
78                     updatePeers(newPeers);
79 
80                     if (newPeers.isEmpty()) {
81                         // Remind system we are still interested
82                         mP2pManager.stopPeerDiscovery(mChannel, null);
83                         mP2pManager.discoverPeers(mChannel, null);
84                     }
85                 }
86             }
87         };
88 
89         mBroadcastMonitor = service.receiveBroadcasts(receiver,
90                 WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION,
91                 WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION);
92         mP2pManager.discoverPeers(mChannel, null);
93     }
94 
addListener(P2pPeerListener listener)95     void addListener(P2pPeerListener listener) {
96         mListeners.add(listener);
97         if (!mPeers.isEmpty()) {
98             for (WifiP2pDevice peer : mPeers) {
99                 listener.onPeerFound(peer);
100             }
101         }
102     }
103 
removeListener(P2pPeerListener listener)104     void removeListener(P2pPeerListener listener) {
105         mListeners.remove(listener);
106     }
107 
getListeners()108     List<P2pPeerListener> getListeners() {
109         return mListeners;
110     }
111 
112     /**
113      * Signal find/loss of each device to listeners as it occurs
114      */
updatePeers(Collection<WifiP2pDevice> newPeers)115     private void updatePeers(Collection<WifiP2pDevice> newPeers) {
116         List<WifiP2pDevice> oldPeers = new ArrayList<>(mPeers);
117 
118         // Reset peer list and populate with new printer-type devices
119         mPeers.clear();
120         for (WifiP2pDevice peer : newPeers) {
121             if (PRINTER_PATTERN.matcher(peer.primaryDeviceType).find()) {
122                 mPeers.add(peer);
123             }
124         }
125 
126         // Notify newly found devices
127         Set<String> foundAddresses = new HashSet<>();
128         for (WifiP2pDevice peer : mPeers) {
129             foundAddresses.add(peer.deviceAddress);
130             WifiP2pDevice old = getDevice(oldPeers, peer.deviceAddress);
131             if (old == null || !old.equals(peer)) {
132                 for (P2pPeerListener listener : mListeners) {
133                     listener.onPeerFound(peer);
134                 }
135             }
136         }
137 
138         // Notify lost devices
139         for (WifiP2pDevice oldPeer : oldPeers) {
140             if (!foundAddresses.contains(oldPeer.deviceAddress)) {
141                 for (P2pPeerListener listener : mListeners) {
142                     listener.onPeerLost(oldPeer);
143                 }
144             }
145         }
146     }
147 
getDevice(Collection<WifiP2pDevice> peers, String address)148     private WifiP2pDevice getDevice(Collection<WifiP2pDevice> peers, String address) {
149         for (WifiP2pDevice found : peers) {
150             if (found.deviceAddress.equals(address)) {
151                 return found;
152             }
153         }
154         return null;
155     }
156 
157     /** Stop the discovery procedure */
cancel()158     public void cancel() {
159         if (DEBUG) Log.d(TAG, "stop()");
160         mBroadcastMonitor.close();
161         if (mChannel != null) {
162             mP2pManager.stopPeerDiscovery(mChannel, null);
163             mChannel.close();
164             mChannel = null;
165         }
166     }
167 }
168