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