1 /*
2  * Copyright (C) 2012 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 package android.net.wifi.p2p;
17 
18 import android.compat.annotation.UnsupportedAppUsage;
19 import android.os.Parcel;
20 import android.os.Parcelable;
21 import android.util.LruCache;
22 
23 import java.util.Collection;
24 import java.util.Map;
25 
26 
27 /**
28  * A class representing a Wi-Fi P2p group list
29  *
30  * {@see WifiP2pManager}
31  * @hide
32  */
33 public class WifiP2pGroupList implements Parcelable {
34 
35     private static final int CREDENTIAL_MAX_NUM             =   32;
36 
37     @UnsupportedAppUsage
38     private final LruCache<Integer, WifiP2pGroup> mGroups;
39     private final GroupDeleteListener mListener;
40 
41     private boolean isClearCalled = false;
42 
43     public interface GroupDeleteListener {
onDeleteGroup(int netId)44         public void onDeleteGroup(int netId);
45     }
46 
47     /** @hide */
WifiP2pGroupList()48     public WifiP2pGroupList() {
49         this(null, null);
50     }
51 
52     /** @hide */
53     @UnsupportedAppUsage
WifiP2pGroupList(WifiP2pGroupList source, GroupDeleteListener listener)54     public WifiP2pGroupList(WifiP2pGroupList source, GroupDeleteListener listener) {
55         mListener = listener;
56         mGroups = new LruCache<Integer, WifiP2pGroup>(CREDENTIAL_MAX_NUM) {
57             @Override
58             protected void entryRemoved(boolean evicted, Integer netId,
59                     WifiP2pGroup oldValue, WifiP2pGroup newValue) {
60                 if (mListener != null && !isClearCalled) {
61                     mListener.onDeleteGroup(oldValue.getNetworkId());
62                 }
63             }
64         };
65 
66         if (source != null) {
67             for (Map.Entry<Integer, WifiP2pGroup> item : source.mGroups.snapshot().entrySet()) {
68                 mGroups.put(item.getKey(), item.getValue());
69             }
70         }
71     }
72 
73     /**
74      * Return the list of p2p group.
75      *
76      * @return the list of p2p group.
77      */
78     @UnsupportedAppUsage
getGroupList()79     public Collection<WifiP2pGroup> getGroupList() {
80         return mGroups.snapshot().values();
81     }
82 
83     /**
84      * Add the specified group to this group list.
85      *
86      * @param group
87      * @hide
88      */
add(WifiP2pGroup group)89     public void add(WifiP2pGroup group) {
90         mGroups.put(group.getNetworkId(), group);
91     }
92 
93     /**
94      * Remove the group with the specified network id from this group list.
95      *
96      * @param netId
97      * @hide
98      */
remove(int netId)99     public void remove(int netId) {
100         mGroups.remove(netId);
101     }
102 
103     /**
104      * Remove the group with the specified device address from this group list.
105      *
106      * @param deviceAddress
107      */
remove(String deviceAddress)108     void remove(String deviceAddress) {
109         remove(getNetworkId(deviceAddress));
110     }
111 
112     /**
113      * Clear the group.
114      * @hide
115      */
clear()116     public boolean clear() {
117         if (mGroups.size() == 0) return false;
118         isClearCalled = true;
119         mGroups.evictAll();
120         isClearCalled = false;
121         return true;
122     }
123 
124     /**
125      * Return the network id of the group owner profile with the specified p2p device
126      * address.
127      * If more than one persistent group of the same address is present in the list,
128      * return the first one.
129      *
130      * @param deviceAddress p2p device address.
131      * @return the network id. if not found, return -1.
132      * @hide
133      */
getNetworkId(String deviceAddress)134     public int getNetworkId(String deviceAddress) {
135         if (deviceAddress == null) return -1;
136 
137         final Collection<WifiP2pGroup> groups = mGroups.snapshot().values();
138         for (WifiP2pGroup grp: groups) {
139             if (deviceAddress.equalsIgnoreCase(grp.getOwner().deviceAddress)) {
140                 // update cache ordered.
141                 mGroups.get(grp.getNetworkId());
142                 return grp.getNetworkId();
143             }
144         }
145         return -1;
146     }
147 
148     /**
149      * Return the network id of the group with the specified p2p device address
150      * and the ssid.
151      *
152      * @param deviceAddress p2p device address.
153      * @param ssid ssid.
154      * @return the network id. if not found, return -1.
155      * @hide
156      */
getNetworkId(String deviceAddress, String ssid)157     public int getNetworkId(String deviceAddress, String ssid) {
158         if (deviceAddress == null || ssid == null) {
159             return -1;
160         }
161 
162         final Collection<WifiP2pGroup> groups = mGroups.snapshot().values();
163         for (WifiP2pGroup grp: groups) {
164             if (deviceAddress.equalsIgnoreCase(grp.getOwner().deviceAddress) &&
165                     ssid.equals(grp.getNetworkName())) {
166                 // update cache ordered.
167                 mGroups.get(grp.getNetworkId());
168                 return grp.getNetworkId();
169             }
170         }
171 
172         return -1;
173     }
174 
175     /**
176      * Return the group owner address of the group with the specified network id
177      *
178      * @param netId network id.
179      * @return the address. if not found, return null.
180      * @hide
181      */
getOwnerAddr(int netId)182     public String getOwnerAddr(int netId) {
183         WifiP2pGroup grp = mGroups.get(netId);
184         if (grp != null) {
185             return grp.getOwner().deviceAddress;
186         }
187         return null;
188     }
189 
190     /**
191      * Return true if this group list contains the specified network id.
192      * This function does NOT update LRU information.
193      * It means the internal queue is NOT reordered.
194      *
195      * @param netId network id.
196      * @return true if the specified network id is present in this group list.
197      * @hide
198      */
contains(int netId)199     public boolean contains(int netId) {
200         final Collection<WifiP2pGroup> groups = mGroups.snapshot().values();
201         for (WifiP2pGroup grp: groups) {
202             if (netId == grp.getNetworkId()) {
203                 return true;
204             }
205         }
206         return false;
207     }
208 
toString()209     public String toString() {
210         StringBuffer sbuf = new StringBuffer();
211 
212         final Collection<WifiP2pGroup> groups = mGroups.snapshot().values();
213         for (WifiP2pGroup grp: groups) {
214             sbuf.append(grp).append("\n");
215         }
216         return sbuf.toString();
217     }
218 
219     /** Implement the Parcelable interface */
describeContents()220     public int describeContents() {
221         return 0;
222     }
223 
224     /** Implement the Parcelable interface */
writeToParcel(Parcel dest, int flags)225     public void writeToParcel(Parcel dest, int flags) {
226         final Collection<WifiP2pGroup> groups = mGroups.snapshot().values();
227         dest.writeInt(groups.size());
228         for(WifiP2pGroup group : groups) {
229             dest.writeParcelable(group, flags);
230         }
231     }
232 
233     /** Implement the Parcelable interface */
234     public static final @android.annotation.NonNull Creator<WifiP2pGroupList> CREATOR =
235         new Creator<WifiP2pGroupList>() {
236             public WifiP2pGroupList createFromParcel(Parcel in) {
237                 WifiP2pGroupList grpList = new WifiP2pGroupList();
238 
239                 int deviceCount = in.readInt();
240                 for (int i = 0; i < deviceCount; i++) {
241                     grpList.add((WifiP2pGroup)in.readParcelable(null));
242                 }
243                 return grpList;
244             }
245 
246             public WifiP2pGroupList[] newArray(int size) {
247                 return new WifiP2pGroupList[size];
248             }
249         };
250 }
251