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