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