1package com.xtremelabs.robolectric.shadows;
2
3import android.net.wifi.ScanResult;
4import android.net.wifi.WifiConfiguration;
5import android.net.wifi.WifiInfo;
6import android.net.wifi.WifiManager;
7import android.util.Pair;
8import com.xtremelabs.robolectric.Robolectric;
9import com.xtremelabs.robolectric.internal.Implementation;
10import com.xtremelabs.robolectric.internal.Implements;
11
12import java.util.ArrayList;
13import java.util.LinkedHashMap;
14import java.util.List;
15import java.util.Map;
16
17import static com.xtremelabs.robolectric.Robolectric.shadowOf;
18
19@SuppressWarnings({"UnusedDeclaration"})
20@Implements(WifiManager.class)
21public class ShadowWifiManager {
22    private static float sSignalLevelInPercent=1f;
23    private boolean accessWifiStatePermission = true;
24    private boolean wifiEnabled = true;
25    private WifiInfo wifiInfo;
26    private List<ScanResult> scanResults;
27    private Map<Integer, WifiConfiguration> networkIdToConfiguredNetworks = new LinkedHashMap<Integer, WifiConfiguration>();
28    public boolean wasSaved;
29    private Pair<Integer, Boolean> lastEnabledNetwork;
30
31    @Implementation
32    public boolean setWifiEnabled(boolean wifiEnabled) {
33        checkAccessWifiStatePermission();
34        this.wifiEnabled = wifiEnabled;
35        return true;
36    }
37
38    @Implementation
39    public boolean isWifiEnabled() {
40        checkAccessWifiStatePermission();
41        return wifiEnabled;
42    }
43
44    @Implementation
45    public WifiInfo getConnectionInfo() {
46        checkAccessWifiStatePermission();
47        if (wifiInfo == null) {
48            wifiInfo = Robolectric.newInstanceOf(WifiInfo.class);
49        }
50        return wifiInfo;
51    }
52
53    @Implementation
54    public List<ScanResult> getScanResults() {
55        return scanResults;
56    }
57
58    @Implementation
59    public List<WifiConfiguration> getConfiguredNetworks() {
60        final ArrayList<WifiConfiguration> wifiConfigurations = new ArrayList<WifiConfiguration>();
61        for (WifiConfiguration wifiConfiguration : networkIdToConfiguredNetworks.values()) {
62            wifiConfigurations.add(wifiConfiguration);
63        }
64        return wifiConfigurations;
65    }
66
67    @Implementation
68    public int addNetwork(WifiConfiguration config) {
69        int networkId = networkIdToConfiguredNetworks.size();
70        config.networkId = -1;
71        networkIdToConfiguredNetworks.put(networkId, makeCopy(config, networkId));
72        return networkId;
73    }
74
75    private WifiConfiguration makeCopy(WifiConfiguration config, int networkId) {
76        WifiConfiguration copy = shadowOf(config).copy();
77        copy.networkId = networkId;
78        return copy;
79    }
80
81
82    @Implementation
83    public int updateNetwork(WifiConfiguration config) {
84        if (config == null || config.networkId < 0) {
85            return -1;
86        }
87        networkIdToConfiguredNetworks.put(config.networkId, makeCopy(config, config.networkId));
88        return config.networkId;
89    }
90
91    @Implementation
92    public boolean saveConfiguration() {
93        wasSaved = true;
94        return true;
95    }
96
97    @Implementation
98    public boolean enableNetwork(int netId, boolean disableOthers) {
99        lastEnabledNetwork = new Pair<Integer, Boolean>(netId, disableOthers);
100        return true;
101    }
102
103    @Implementation
104    public WifiManager.WifiLock createWifiLock(int lockType, java.lang.String tag) {
105        return Robolectric.newInstanceOf(WifiManager.WifiLock.class);
106    }
107
108    @Implementation
109    public WifiManager.WifiLock createWifiLock(java.lang.String tag) {
110        return createWifiLock(WifiManager.WIFI_MODE_FULL, tag);
111    }
112
113    @Implementation
114    public static int calculateSignalLevel (int rssi, int numLevels)
115    {
116        return (int)(sSignalLevelInPercent*(numLevels-1));
117    }
118
119    public static void setSignalLevelInPercent(float level) {
120        if (level < 0 || level > 1) {
121            throw new IllegalArgumentException(
122                    "level needs to be between 0 and 1");
123        }
124        sSignalLevelInPercent = level;
125    }
126
127    public void setAccessWifiStatePermission(boolean accessWifiStatePermission) {
128        this.accessWifiStatePermission = accessWifiStatePermission;
129    }
130
131    private void checkAccessWifiStatePermission() {
132        if (!accessWifiStatePermission) {
133            throw new SecurityException();
134        }
135    }
136
137    public void setScanResults(List<ScanResult> scanResults) {
138        this.scanResults = scanResults;
139    }
140
141    public Pair<Integer, Boolean> getLastEnabledNetwork() {
142        return lastEnabledNetwork;
143    }
144
145
146    @Implements(WifiManager.WifiLock.class)
147    public static class ShadowWifiLock {
148        private int refCount;
149        private boolean refCounted = true;
150        private boolean locked;
151        public static final int MAX_ACTIVE_LOCKS = 50;
152
153        @Implementation
154        public synchronized void acquire() {
155            if (refCounted) {
156                if (++refCount >= MAX_ACTIVE_LOCKS) throw new UnsupportedOperationException("Exceeded maximum number of wifi locks");
157            } else {
158                locked = true;
159            }
160        }
161
162        @Implementation
163        public synchronized void release() {
164            if (refCounted) {
165                if (--refCount < 0) throw new RuntimeException("WifiLock under-locked");
166            } else {
167                locked = false;
168            }
169        }
170
171        @Implementation
172        public synchronized boolean isHeld() {
173            return refCounted ? refCount > 0 : locked;
174        }
175
176        @Implementation
177        public void setReferenceCounted(boolean refCounted) {
178            this.refCounted = refCounted;
179        }
180    }
181}
182