| package com.googlecode.android_scripting.facade; |
| |
| import android.app.Service; |
| import android.content.Context; |
| import android.net.wifi.ScanResult; |
| import android.net.wifi.WifiScanner; |
| import android.net.wifi.WifiScanner.*; |
| import android.os.Bundle; |
| |
| import com.googlecode.android_scripting.Log; |
| import com.googlecode.android_scripting.MainThread; |
| import com.googlecode.android_scripting.jsonrpc.RpcReceiver; |
| import com.googlecode.android_scripting.rpc.Rpc; |
| import com.googlecode.android_scripting.rpc.RpcParameter; |
| import com.googlecode.android_scripting.rpc.RpcStartEvent; |
| import com.googlecode.android_scripting.rpc.RpcStopEvent; |
| |
| import java.util.Hashtable; |
| import java.util.concurrent.Callable; |
| |
| /** |
| * ScanManager functions. |
| * |
| */ |
| public class ScanFacade extends RpcReceiver { |
| private final Service mService; |
| private final EventFacade mEventFacade; |
| private final WifiScanner mScan; |
| // These counters are just for indexing; |
| // they do not represent the total number of listeners |
| private static int WifiScanListenerCnt; |
| private static int WifiChangeListenerCnt; |
| private static int WifiHotspotListenerCnt; |
| private Hashtable<Integer, WifiScanListener> wifiScannerListenerList; |
| private Hashtable<Integer, ChangeListener> wifiChangeListenerList; |
| private Hashtable<Integer, WifiHotspotListener> wifiHotspotListenerList; |
| |
| public ScanFacade(FacadeManager manager) { |
| super(manager); |
| mService = manager.getService(); |
| mScan = (WifiScanner) mService.getSystemService(Context.WIFI_SCANNING_SERVICE); |
| mEventFacade = manager.getReceiver(EventFacade.class); |
| wifiScannerListenerList = new Hashtable<Integer, WifiScanListener>(); |
| wifiChangeListenerList = new Hashtable<Integer, ChangeListener>(); |
| wifiHotspotListenerList = new Hashtable<Integer, WifiHotspotListener>(); |
| } |
| |
| private class WifiActionListener implements WifiScanner.ActionListener { |
| private final Bundle mStatus; |
| private final Bundle mResults; |
| public int index; |
| protected String listenerType; |
| |
| public WifiActionListener(String type, int idx, Bundle statusBundle, Bundle resultBundle) { |
| index = idx; |
| listenerType = type; |
| mStatus = statusBundle; |
| mResults = resultBundle; |
| } |
| |
| @Override |
| public void onSuccess(Object result) { |
| Log.d("android_scripting change onSuccess " + listenerType + index); |
| mStatus.putString("ID", listenerType + index); |
| mStatus.putBoolean("Status", true); |
| mEventFacade.postEvent("Started", mStatus.clone()); |
| mStatus.clear(); |
| } |
| |
| @Override |
| public void onFailure(int reason, Object exception) { |
| Log.d("android_scripting change onFailure " + listenerType + index); |
| mStatus.putString("ID", listenerType + index); |
| mStatus.putBoolean("Status", false); |
| mStatus.putInt("Reason", reason); |
| mStatus.putString("Exception", exception.toString()); |
| mEventFacade.postEvent("Failed", mStatus.clone()); |
| mStatus.clear(); |
| } |
| |
| public void reportResult(ScanResult[] results, String eventType) { |
| Log.d("android_scripting " + eventType + " " + listenerType + index); |
| mResults.putString("ID", listenerType + index); |
| mResults.putString("Type", eventType); |
| mResults.putParcelableArray("Results", results); |
| mResults.putLong("Time", System.currentTimeMillis()); |
| mEventFacade.postEvent("ScanResults", mResults.clone()); |
| mResults.clear(); |
| } |
| |
| } |
| |
| /** |
| * Constructs a wifiScanListener obj and returns it |
| * |
| * @return WifiScanListener |
| */ |
| private WifiScanListener genWifiScanListener() { |
| WifiScanListener mWifiScannerListener = |
| MainThread.run(mService, new Callable<WifiScanListener>() { |
| @Override |
| public WifiScanListener call() throws Exception { |
| return new WifiScanListener(); |
| } |
| }); |
| wifiScannerListenerList.put(mWifiScannerListener.index, mWifiScannerListener); |
| return mWifiScannerListener; |
| } |
| |
| private class WifiScanListener implements WifiScanner.ScanListener { |
| protected final Bundle mScanResults; |
| protected final Bundle mScanStatus; |
| private final WifiActionListener mWAL; |
| public int index; |
| |
| public WifiScanListener() { |
| mScanStatus = new Bundle(); |
| mScanResults = new Bundle(); |
| WifiScanListenerCnt += 1; |
| index = WifiScanListenerCnt; |
| mWAL = new WifiActionListener("WifiScanListener", index, mScanStatus, mScanResults); |
| } |
| |
| @Override |
| public void onSuccess(Object result) { |
| mWAL.onSuccess(result); |
| } |
| |
| @Override |
| public void onFailure(int reason, Object exception) { |
| mWAL.onFailure(reason, exception); |
| } |
| |
| @Override |
| public void onPeriodChanged(int periodInMs) { |
| mScanStatus.putString("ID", "WifiScanListener" + index); |
| mScanStatus.putBoolean("Status", true); |
| mScanStatus.putInt("NewPeriod", periodInMs); |
| mEventFacade.postEvent("onPeriodChanged", mScanStatus.clone()); |
| mScanStatus.clear(); |
| } |
| |
| @Override |
| public void onResults(ScanResult[] results) { |
| mWAL.reportResult(results, "onScanResults"); |
| } |
| |
| @Override |
| public void onFullResult(FullScanResult fullScanResult) { |
| Log.d("android_scripting onFullResult WifiScanListener " + index); |
| mScanResults.putString("ID", "WifiScanListener" + index); |
| mScanResults.putString("ScanResult", fullScanResult.result.toString()); |
| for (InformationElement ie : fullScanResult.informationElements) { |
| mScanResults.putInt("ExtraInfoId", ie.id); |
| mScanResults.putByteArray("ExtraInfoBytes", ie.bytes); |
| } |
| mEventFacade.postEvent("onFullResult", mScanResults.clone()); |
| mScanResults.clear(); |
| } |
| } |
| |
| /** |
| * Constructs a ChangeListener obj and returns it |
| * |
| * @return ChangeListener |
| */ |
| public ChangeListener genWifiChangeListener() { |
| ChangeListener mWifiChangeListener = MainThread.run(mService, new Callable<ChangeListener>() { |
| @Override |
| public ChangeListener call() throws Exception { |
| return new ChangeListener(); |
| } |
| }); |
| wifiChangeListenerList.put(mWifiChangeListener.index, mWifiChangeListener); |
| return mWifiChangeListener; |
| } |
| |
| private class ChangeListener implements WifiScanner.WifiChangeListener { |
| protected final Bundle mStatus; |
| protected final Bundle mResults; |
| private final WifiActionListener mWAL; |
| public int index; |
| |
| public ChangeListener() { |
| mStatus = new Bundle(); |
| mResults = new Bundle(); |
| WifiChangeListenerCnt += 1; |
| index = WifiChangeListenerCnt; |
| mWAL = new WifiActionListener("WifiChangeListener", index, mStatus, mResults); |
| } |
| |
| @Override |
| public void onSuccess(Object result) { |
| mWAL.onSuccess(result); |
| } |
| |
| @Override |
| public void onFailure(int reason, Object exception) { |
| mWAL.onFailure(reason, exception); |
| } |
| |
| /** |
| * indicates that changes were detected in wifi environment |
| * |
| * @param results |
| * indicate the access points that exhibited change |
| */ |
| @Override |
| public void onChanging(ScanResult[] results) { /* changes are found */ |
| mWAL.reportResult(results, "onChanging"); |
| } |
| |
| /** |
| * indicates that no wifi changes are being detected for a while |
| * |
| * @param results |
| * indicate the access points that are bing monitored for change |
| */ |
| @Override |
| public void onQuiescence(ScanResult[] results) { /* changes settled down */ |
| mWAL.reportResult(results, "onQuiescence"); |
| } |
| } |
| |
| public WifiHotspotListener genWifiHotspotListener() { |
| WifiHotspotListener mWifiHotspotListener = |
| MainThread.run(mService, new Callable<WifiHotspotListener>() { |
| @Override |
| public WifiHotspotListener call() throws Exception { |
| return new WifiHotspotListener(); |
| } |
| }); |
| wifiHotspotListenerList.put(mWifiHotspotListener.index, mWifiHotspotListener); |
| return mWifiHotspotListener; |
| } |
| |
| private class WifiHotspotListener implements WifiScanner.HotlistListener { |
| protected final Bundle mStatus; |
| protected final Bundle mResults; |
| private final WifiActionListener mWAL; |
| public int index; |
| |
| public WifiHotspotListener() { |
| mStatus = new Bundle(); |
| mResults = new Bundle(); |
| WifiHotspotListenerCnt += 1; |
| index = WifiHotspotListenerCnt; |
| mWAL = new WifiActionListener("HotspotListener", index, mStatus, mResults); |
| } |
| |
| @Override |
| public void onSuccess(Object result) { |
| mWAL.onSuccess(result); |
| } |
| |
| @Override |
| public void onFailure(int reason, Object exception) { |
| mWAL.onFailure(reason, exception); |
| } |
| |
| @Override |
| public void onFound(ScanResult[] results) { |
| mWAL.reportResult(results, "onHotspotFound"); |
| } |
| } |
| |
| /** RPC Method Section */ |
| |
| /** |
| * Starts periodic wifi background scan |
| * |
| * @param periodInMs |
| * @param channel_freqs |
| * frequencies of channels to scan |
| * @return the id of the scan listener associated with this scan |
| */ |
| @Rpc(description = "Starts a periodic Wifi scan in background.") |
| @RpcStartEvent("WifiScan") |
| public Integer startWifiBackgroundScan(@RpcParameter(name = "periodInMs") Integer periodInMs, |
| @RpcParameter(name = "channel_freqs") Integer[] channel_freqs) { |
| WifiScanner.ScanSettings ss = new WifiScanner.ScanSettings(); |
| ss.channels = new WifiScanner.ChannelSpec[channel_freqs.length]; |
| for (int i = 0; i < channel_freqs.length; i++) { |
| ss.channels[i] = new WifiScanner.ChannelSpec(channel_freqs[i]); |
| } |
| ss.periodInMs = periodInMs; |
| Log.d("android_scripting periodInMs " + ss.periodInMs); |
| for (int i = 0; i < ss.channels.length; i++) { |
| Log.d("android_scripting " + ss.channels[i].frequency + " " + ss.channels[i].passive + " " |
| + ss.channels[i].dwellTimeMS); |
| } |
| WifiScanListener mListener = genWifiScanListener(); |
| mScan.startBackgroundScan(ss, mListener); |
| return mListener.index; |
| } |
| |
| /** |
| * Stops a wifi background scan |
| * |
| * @param listener_index |
| * the id of the scan listener whose scan to stop |
| */ |
| @Rpc(description = "Stops an ongoing periodic Wifi scan in background") |
| @RpcStopEvent("WifiScan") |
| public void stopWifiBackgroundScan(@RpcParameter(name = "listener") Integer listener_index) { |
| Log.d("android_scripting stopping background scan"); |
| WifiScanListener mListener = wifiScannerListenerList.get(listener_index); |
| Log.d("android_scripting mListener " + mListener.index + mListener.toString()); |
| mScan.stopBackgroundScan(mListener); |
| wifiScannerListenerList.remove(listener_index); |
| } |
| |
| @Rpc(description = "Returns a list of indexes of existing listeners") |
| public Integer[] showWifiScanListeners() { |
| Integer[] result = new Integer[wifiScannerListenerList.size()]; |
| int j = 0; |
| for (int i : wifiScannerListenerList.keySet()) { |
| result[j] = wifiScannerListenerList.get(i).index; |
| j += 1; |
| } |
| return result; |
| } |
| |
| /** |
| * Starts tracking wifi changes |
| * |
| * @return the id of the change listener associated with this track |
| */ |
| @Rpc(description = "Starts tracking wifi changes") |
| public Integer startTrackingChange() { |
| Log.d("android_scripting starting change track"); |
| ChangeListener mListener = genWifiChangeListener(); |
| mScan.startTrackingWifiChange(mListener); |
| return mListener.index; |
| } |
| |
| /** |
| * Stops tracking wifi changes |
| * |
| * @param listener_index |
| * the id of the change listener whose track to stop |
| */ |
| @Rpc(description = "Stops tracking wifi changes") |
| public void stopTrackingChange(@RpcParameter(name = "listener") Integer listener_index) { |
| ChangeListener mListener = wifiChangeListenerList.get(listener_index); |
| mScan.stopTrackingWifiChange(mListener); |
| wifiChangeListenerList.remove(listener_index); |
| } |
| |
| /** |
| * Starts tracking changes of the wifi networks specified in a hotlist |
| * |
| * @param hotspotInfos |
| * a 'hotlist' specifying which wifi networks to track |
| * @param apLostThreshold |
| * signal strength below which an AP is considered lost |
| * @return the id of the hotlist listener associated with this track |
| * @throws Exception |
| */ |
| @Rpc(description = "Starts tracking changes of the APs on hotlist") |
| public Integer setHotlist(String[] hotspotInfos, Integer apLostThreshold) throws Exception { |
| // Instantiates HotspotInfo objs |
| HotspotInfo[] mHotspotInfos = new HotspotInfo[hotspotInfos.length]; |
| for (int i = 0; i < hotspotInfos.length; i++) { |
| Log.d("android_scripting " + hotspotInfos[i]); |
| String[] tokens = hotspotInfos[i].split(" "); |
| if (tokens.length != 3) { |
| throw new Exception("Invalid hotspot info: " + hotspotInfos[i]); |
| |
| } |
| int a = Integer.parseInt(tokens[1]); |
| int b = Integer.parseInt(tokens[2]); |
| HotspotInfo mHI = new HotspotInfo(); |
| mHI.bssid = tokens[0]; |
| mHI.low = a < b ? a : b; |
| mHI.high = a < b ? b : a; |
| mHotspotInfos[i] = mHI; |
| } |
| WifiHotspotListener mWHL = genWifiHotspotListener(); |
| mScan.setHotlist(mHotspotInfos, apLostThreshold, mWHL); |
| return mWHL.index; |
| } |
| |
| /** |
| * Stops tracking the hotlist associated with the input listener |
| * |
| * @param listener_index |
| * the id of the hotspot listener whose track to stop |
| */ |
| @Rpc(description = "Stops tracking changes of the APs on hotlist") |
| public void resetHotlist(@RpcParameter(name = "listener") Integer listener_index) { |
| WifiHotspotListener mListener = wifiHotspotListenerList.get(listener_index); |
| mScan.resetHotlist(mListener); |
| wifiHotspotListenerList.remove(listener_index); |
| } |
| |
| /** |
| * Shuts down all activities associated with WifiScanner |
| */ |
| @Rpc(description = "Shuts down all WifiScanner activities") |
| public void wifiScannerShutdown() { |
| shutdown(); |
| } |
| |
| /** |
| * Stops all activity |
| */ |
| @Override |
| public void shutdown() { |
| if (!wifiScannerListenerList.isEmpty()) { |
| for (int i : wifiScannerListenerList.keySet()) { |
| stopWifiBackgroundScan(i); |
| } |
| } |
| if (!wifiChangeListenerList.isEmpty()) { |
| for (int i : wifiChangeListenerList.keySet()) { |
| stopTrackingChange(i); |
| } |
| } |
| if (!wifiHotspotListenerList.isEmpty()) { |
| for (int i : wifiHotspotListenerList.keySet()) { |
| resetHotlist(i); |
| } |
| } |
| } |
| } |