1package com.android.server.wifi;
2
3import android.content.pm.UserInfo;
4import android.net.wifi.WifiConfiguration;
5import android.os.UserHandle;
6import android.os.UserManager;
7
8import java.util.ArrayList;
9import java.util.Collection;
10import java.util.HashMap;
11import java.util.HashSet;
12import java.util.Iterator;
13import java.util.List;
14import java.util.Map;
15import java.util.Set;
16
17public class ConfigurationMap {
18    private final Map<Integer, WifiConfiguration> mPerID = new HashMap<>();
19    private final Map<Integer, WifiConfiguration> mPerConfigKey = new HashMap<>();
20
21    private final Map<Integer, WifiConfiguration> mPerIDForCurrentUser = new HashMap<>();
22    private final Map<String, WifiConfiguration> mPerFQDNForCurrentUser = new HashMap<>();
23    /**
24     * List of all hidden networks in the current user's configuration.
25     * Use this list as a param for directed scanning .
26     */
27    private final Set<Integer> mHiddenNetworkIdsForCurrentUser = new HashSet<>();
28
29    private final UserManager mUserManager;
30
31    private int mCurrentUserId = UserHandle.USER_SYSTEM;
32
33    ConfigurationMap(UserManager userManager) {
34        mUserManager = userManager;
35    }
36
37    // RW methods:
38    public WifiConfiguration put(WifiConfiguration config) {
39        final WifiConfiguration current = mPerID.put(config.networkId, config);
40        mPerConfigKey.put(config.configKey().hashCode(), config);   // This is ridiculous...
41        if (WifiConfigurationUtil.isVisibleToAnyProfile(config,
42                mUserManager.getProfiles(mCurrentUserId))) {
43            mPerIDForCurrentUser.put(config.networkId, config);
44            if (config.FQDN != null && config.FQDN.length() > 0) {
45                mPerFQDNForCurrentUser.put(config.FQDN, config);
46            }
47            if (config.hiddenSSID) {
48                mHiddenNetworkIdsForCurrentUser.add(config.networkId);
49            }
50        }
51        return current;
52    }
53
54    public WifiConfiguration remove(int netID) {
55        WifiConfiguration config = mPerID.remove(netID);
56        if (config == null) {
57            return null;
58        }
59        mPerConfigKey.remove(config.configKey().hashCode());
60
61        mPerIDForCurrentUser.remove(netID);
62        Iterator<Map.Entry<String, WifiConfiguration>> entries =
63                mPerFQDNForCurrentUser.entrySet().iterator();
64        while (entries.hasNext()) {
65            if (entries.next().getValue().networkId == netID) {
66                entries.remove();
67                break;
68            }
69        }
70        mHiddenNetworkIdsForCurrentUser.remove(netID);
71        return config;
72    }
73
74    public void clear() {
75        mPerID.clear();
76        mPerConfigKey.clear();
77        mPerIDForCurrentUser.clear();
78        mPerFQDNForCurrentUser.clear();
79        mHiddenNetworkIdsForCurrentUser.clear();
80    }
81
82    /**
83     * Handles the switch to a different foreground user:
84     * - Hides private network configurations belonging to the previous foreground user
85     * - Reveals private network configurations belonging to the new foreground user
86     *
87     * @param userId the id of the new foreground user
88     * @return a list of {@link WifiConfiguration}s that became hidden because of the user switch
89     */
90    public List<WifiConfiguration> handleUserSwitch(int userId) {
91        mPerIDForCurrentUser.clear();
92        mPerFQDNForCurrentUser.clear();
93        mHiddenNetworkIdsForCurrentUser.clear();
94
95        final List<UserInfo> previousUserProfiles = mUserManager.getProfiles(mCurrentUserId);
96        mCurrentUserId = userId;
97        final List<UserInfo> currentUserProfiles = mUserManager.getProfiles(mCurrentUserId);
98
99        final List<WifiConfiguration> hiddenConfigurations = new ArrayList<>();
100        for (Map.Entry<Integer, WifiConfiguration> entry : mPerID.entrySet()) {
101            final WifiConfiguration config = entry.getValue();
102            if (WifiConfigurationUtil.isVisibleToAnyProfile(config, currentUserProfiles)) {
103                mPerIDForCurrentUser.put(entry.getKey(), config);
104                if (config.FQDN != null && config.FQDN.length() > 0) {
105                    mPerFQDNForCurrentUser.put(config.FQDN, config);
106                }
107                if (config.hiddenSSID) {
108                    mHiddenNetworkIdsForCurrentUser.add(config.networkId);
109                }
110            } else if (WifiConfigurationUtil.isVisibleToAnyProfile(config, previousUserProfiles)) {
111                hiddenConfigurations.add(config);
112            }
113        }
114
115        return hiddenConfigurations;
116    }
117
118    // RO methods:
119    public WifiConfiguration getForAllUsers(int netid) {
120        return mPerID.get(netid);
121    }
122
123    public WifiConfiguration getForCurrentUser(int netid) {
124        return mPerIDForCurrentUser.get(netid);
125    }
126
127    public int sizeForAllUsers() {
128        return mPerID.size();
129    }
130
131    public int sizeForCurrentUser() {
132        return mPerIDForCurrentUser.size();
133    }
134
135    public WifiConfiguration getByFQDNForCurrentUser(String fqdn) {
136        return mPerFQDNForCurrentUser.get(fqdn);
137    }
138
139    public WifiConfiguration getByConfigKeyForCurrentUser(String key) {
140        if (key == null) {
141            return null;
142        }
143        for (WifiConfiguration config : mPerIDForCurrentUser.values()) {
144            if (config.configKey().equals(key)) {
145                return config;
146            }
147        }
148        return null;
149    }
150
151    public WifiConfiguration getByConfigKeyIDForAllUsers(int id) {
152        return mPerConfigKey.get(id);
153    }
154
155    public Collection<WifiConfiguration> getEnabledNetworksForCurrentUser() {
156        List<WifiConfiguration> list = new ArrayList<>();
157        for (WifiConfiguration config : mPerIDForCurrentUser.values()) {
158            if (config.status != WifiConfiguration.Status.DISABLED) {
159                list.add(config);
160            }
161        }
162        return list;
163    }
164
165    public WifiConfiguration getEphemeralForCurrentUser(String ssid) {
166        for (WifiConfiguration config : mPerIDForCurrentUser.values()) {
167            if (ssid.equals(config.SSID) && config.ephemeral) {
168                return config;
169            }
170        }
171        return null;
172    }
173
174    public Collection<WifiConfiguration> valuesForAllUsers() {
175        return mPerID.values();
176    }
177
178    public Collection<WifiConfiguration> valuesForCurrentUser() {
179        return mPerIDForCurrentUser.values();
180    }
181
182    public Set<Integer> getHiddenNetworkIdsForCurrentUser() {
183        return mHiddenNetworkIdsForCurrentUser;
184    }
185}
186