FileDocCategorySizeDatePackage
WifiScanningServiceImpl.javaAPI DocAndroid 5.1 API64050Thu Mar 12 22:22:52 GMT 2015com.android.server.wifi

WifiScanningServiceImpl

public class WifiScanningServiceImpl extends IWifiScanner.Stub

Fields Summary
private static final String
TAG
private static final boolean
DBG
private static final int
INVALID_KEY
private static final int
MIN_PERIOD_PER_CHANNEL_MS
private static final int
BASE
private static final int
CMD_SCAN_RESULTS_AVAILABLE
private static final int
CMD_FULL_SCAN_RESULTS
private static final int
CMD_HOTLIST_AP_FOUND
private static final int
CMD_HOTLIST_AP_LOST
private static final int
CMD_WIFI_CHANGE_DETECTED
private static final int
CMD_WIFI_CHANGES_STABILIZED
private static final int
CMD_DRIVER_LOADED
private static final int
CMD_DRIVER_UNLOADED
private static final int
CMD_SCAN_PAUSED
private static final int
CMD_SCAN_RESTARTED
private android.content.Context
mContext
private WifiScanningStateMachine
mStateMachine
private ClientHandler
mClientHandler
HashMap
mClients
WifiChangeStateMachine
mWifiChangeStateMachine
Constructors Summary
WifiScanningServiceImpl()


      
WifiScanningServiceImpl(android.content.Context context)

        mContext = context;
    
Methods Summary
booleanaddScanRequest(com.android.server.wifi.WifiScanningServiceImpl$ClientInfo ci, int handler, android.net.wifi.WifiScanner.ScanSettings settings)

        // sanity check the input
        if (settings.periodInMs < WifiScanner.MIN_SCAN_PERIOD_MS) {
            Log.d(TAG, "Failing scan request because periodInMs is " + settings.periodInMs);
            return false;
        }

        int minSupportedPeriodMs = 0;
        if (settings.channels != null) {
            minSupportedPeriodMs = settings.channels.length * MIN_PERIOD_PER_CHANNEL_MS;
        } else {
            if ((settings.band & WifiScanner.WIFI_BAND_24_GHZ) == 0) {
                /* 2.4 GHz band has 11 to 13 channels */
                minSupportedPeriodMs += 1000;
            }
            if ((settings.band & WifiScanner.WIFI_BAND_5_GHZ) == 0) {
                /* 5 GHz band has another 10 channels */
                minSupportedPeriodMs += 1000;
            }
            if ((settings.band & WifiScanner.WIFI_BAND_5_GHZ_DFS_ONLY) == 0) {
                /* DFS requires passive scan which takes longer time */
                minSupportedPeriodMs += 2000;
            }
        }

        if (settings.periodInMs < minSupportedPeriodMs) {
            Log.d(TAG, "Failing scan request because minSupportedPeriodMs is "
                    + minSupportedPeriodMs + " but the request wants " + settings.periodInMs);
            return false;
        }

        ci.addScanRequest(settings, handler);
        if (resetBuckets()) {
            return true;
        } else {
            ci.removeScanRequest(handler);
            Log.d(TAG, "Failing scan request because failed to reset scan");
            return false;
        }
    
voidconfigureWifiChange(WifiScanner.WifiChangeSettings settings)

        mWifiChangeStateMachine.configure(settings);
    
private voidenforceConnectivityInternalPermission()

        mContext.enforceCallingOrSelfPermission(
                android.Manifest.permission.CONNECTIVITY_INTERNAL,
                "WifiScanningServiceImpl");
    
public android.os.BundlegetAvailableChannels(int band)

        WifiScanner.ChannelSpec channelSpecs[] = getChannelsForBand(band);
        ArrayList<Integer> list = new ArrayList<Integer>(channelSpecs.length);
        for (WifiScanner.ChannelSpec channelSpec : channelSpecs) {
            list.add(channelSpec.frequency);
        }
        Bundle b = new Bundle();
        b.putIntegerArrayList(WifiScanner.GET_AVAILABLE_CHANNELS_EXTRA, list);
        return b;
    
private static intgetBandFromChannels(WifiScanner.ChannelSpec[] channels)

        int band = WifiScanner.WIFI_BAND_UNSPECIFIED;
        for (WifiScanner.ChannelSpec channel : channels) {
            if (2400 <= channel.frequency && channel.frequency < 2500) {
                band |= WifiScanner.WIFI_BAND_24_GHZ;
            } else if (5100 <= channel.frequency && channel.frequency < 6000) {
                band |= WifiScanner.WIFI_BAND_5_GHZ;
            } else {
                /* TODO: Add DFS Range */
            }
        }
        return band;
    
private static intgetBandFromChannels(WifiNative.ChannelSettings[] channels)

        int band = WifiScanner.WIFI_BAND_UNSPECIFIED;
        for (WifiNative.ChannelSettings channel : channels) {
            if (2400 <= channel.frequency && channel.frequency < 2500) {
                band |= WifiScanner.WIFI_BAND_24_GHZ;
            } else if (5100 <= channel.frequency && channel.frequency < 6000) {
                band |= WifiScanner.WIFI_BAND_5_GHZ;
            } else {
                /* TODO: Add DFS Range */
            }
        }
        return band;
    
private static WifiScanner.ChannelSpec[]getChannelsForBand(int band)

        int channels[] = WifiNative.getChannelsForBand(band);
        if (channels != null) {
            WifiScanner.ChannelSpec channelSpecs[] = new WifiScanner.ChannelSpec[channels.length];
            for (int i = 0; i < channels.length; i++) {
                channelSpecs[i] = new WifiScanner.ChannelSpec(channels[i]);
            }
            return channelSpecs;
        } else {
            return new WifiScanner.ChannelSpec[0];
        }
    
public android.os.MessengergetMessenger()

               // DFS needs 120 ms

    
       
        return new Messenger(mClientHandler);
    
android.net.wifi.ScanResult[]getScanResults(com.android.server.wifi.WifiScanningServiceImpl$ClientInfo ci)

        ScanResult results[] = WifiNative.getScanResults();
        ci.reportScanResults(results);
        return results;
    
voidremoveScanRequest(com.android.server.wifi.WifiScanningServiceImpl$ClientInfo ci, int handler)

        ci.removeScanRequest(handler);
        resetBuckets();
    
voidreplyFailed(android.os.Message msg, int reason, java.lang.String description)

        if (msg.replyTo != null) {
            Message reply = Message.obtain();
            reply.what = WifiScanner.CMD_OP_FAILED;
            reply.arg2 = msg.arg2;
            reply.obj = new WifiScanner.OperationResult(reason, description);
            try {
                msg.replyTo.send(reply);
            } catch (RemoteException e) {
                // There's not much we can do if reply can't be sent!
            }
        } else {
            // locally generated message; doesn't need a reply!
        }
    
voidreplySucceeded(android.os.Message msg, java.lang.Object obj)

        if (msg.replyTo != null) {
            Message reply = Message.obtain();
            reply.what = WifiScanner.CMD_OP_SUCCEEDED;
            reply.arg2 = msg.arg2;
            reply.obj = obj;
            try {
                msg.replyTo.send(reply);
            } catch (RemoteException e) {
                // There's not much we can do if reply can't be sent!
            }
        } else {
            // locally generated message; doesn't need a reply!
        }
    
voidreportWifiChanged(android.net.wifi.ScanResult[] results)

        Collection<ClientInfo> clients = mClients.values();
        for (ClientInfo ci : clients) {
            ci.reportWifiChanged(results);
        }
    
voidreportWifiStabilized(android.net.wifi.ScanResult[] results)

        Collection<ClientInfo> clients = mClients.values();
        for (ClientInfo ci : clients) {
            ci.reportWifiStabilized(results);
        }
    
booleanresetBuckets()

        SettingsComputer c = new SettingsComputer();
        Collection<ClientInfo> clients = mClients.values();
        for (ClientInfo ci : clients) {
            Collection<ScanSettings> settings = ci.getScanSettings();
            for (ScanSettings s : settings) {
                c.prepChannelMap(s);
            }
        }

        for (ClientInfo ci : clients) {
            Iterator it = ci.getScans();
            while (it.hasNext()) {
                Map.Entry<Integer, WifiScanner.ScanSettings> entry =
                        (Map.Entry<Integer,WifiScanner.ScanSettings>)it.next();
                int id = entry.getKey();
                ScanSettings s = entry.getValue();
                int newPeriodInMs = c.addScanRequestToBucket(s);
                if (newPeriodInMs  == -1) {
                    if (DBG) Log.d(TAG, "could not find a good bucket");
                    return false;
                }
                if (newPeriodInMs != s.periodInMs) {
                    ci.reportPeriodChanged(id, s, newPeriodInMs);
                }
            }
        }

        c.compressBuckets();

        WifiNative.ScanSettings s = c.getComputedSettings();
        if (s.num_buckets == 0) {
            if (DBG) Log.d(TAG, "Stopping scan because there are no buckets");
            WifiNative.stopScan();
            return true;
        } else {
            if (WifiNative.startScan(s, mStateMachine)) {
                if (DBG) Log.d(TAG, "Successfully started scan of " + s.num_buckets + " buckets at"
                        + "time = " + SystemClock.elapsedRealtimeNanos()/1000);
                return true;
            } else {
                if (DBG) Log.d(TAG, "Failed to start scan of " + s.num_buckets + " buckets");
                return false;
            }
        }
    
voidresetHotlist()

        Collection<ClientInfo> clients = mClients.values();
        int num_hotlist_ap = 0;

        for (ClientInfo ci : clients) {
            Collection<WifiScanner.HotlistSettings> c = ci.getHotlistSettings();
            for (WifiScanner.HotlistSettings s : c) {
                num_hotlist_ap +=  s.bssidInfos.length;
            }
        }

        if (num_hotlist_ap == 0) {
            WifiNative.resetHotlist();
        } else {
            WifiScanner.BssidInfo bssidInfos[] = new WifiScanner.BssidInfo[num_hotlist_ap];
            int index = 0;
            for (ClientInfo ci : clients) {
                Collection<WifiScanner.HotlistSettings> settings = ci.getHotlistSettings();
                for (WifiScanner.HotlistSettings s : settings) {
                    for (int i = 0; i < s.bssidInfos.length; i++, index++) {
                        bssidInfos[index] = s.bssidInfos[i];
                    }
                }
            }

            WifiScanner.HotlistSettings settings = new WifiScanner.HotlistSettings();
            settings.bssidInfos = bssidInfos;
            settings.apLostThreshold = 3;
            WifiNative.setHotlist(settings, mStateMachine);
        }
    
voidresetHotlist(com.android.server.wifi.WifiScanningServiceImpl$ClientInfo ci, int handler)

        ci.removeHostlistSettings(handler);
        resetHotlist();
    
voidsetHotlist(com.android.server.wifi.WifiScanningServiceImpl$ClientInfo ci, int handler, WifiScanner.HotlistSettings settings)

        ci.addHostlistSettings(settings, handler);
        resetHotlist();
    
public voidstartService(android.content.Context context)

        mContext = context;

        HandlerThread thread = new HandlerThread("WifiScanningService");
        thread.start();

        mClientHandler = new ClientHandler(thread.getLooper());
        mStateMachine = new WifiScanningStateMachine(thread.getLooper());
        mWifiChangeStateMachine = new WifiChangeStateMachine(thread.getLooper());

        mContext.registerReceiver(
                new BroadcastReceiver() {
                    @Override
                    public void onReceive(Context context, Intent intent) {
                        int state = intent.getIntExtra(
                                WifiManager.EXTRA_SCAN_AVAILABLE, WifiManager.WIFI_STATE_DISABLED);
                        if (DBG) Log.d(TAG, "SCAN_AVAILABLE : " + state);
                        if (state == WifiManager.WIFI_STATE_ENABLED) {
                            mStateMachine.sendMessage(CMD_DRIVER_LOADED);
                        } else if (state == WifiManager.WIFI_STATE_DISABLED) {
                            mStateMachine.sendMessage(CMD_DRIVER_UNLOADED);
                        }
                    }
                }, new IntentFilter(WifiManager.WIFI_SCAN_AVAILABLE));

        mStateMachine.start();
        mWifiChangeStateMachine.start();
    
voidtrackWifiChanges(com.android.server.wifi.WifiScanningServiceImpl$ClientInfo ci, int handler)

        mWifiChangeStateMachine.enable();
        ci.addSignificantWifiChange(handler);
    
voiduntrackWifiChanges(com.android.server.wifi.WifiScanningServiceImpl$ClientInfo ci, int handler)

        ci.removeSignificantWifiChange(handler);
        Collection<ClientInfo> clients = mClients.values();
        for (ClientInfo ci2 : clients) {
            if (ci2.getWifiChangeHandlers().size() != 0) {
                // there is at least one client watching for
                // significant changes; so nothing more to do
                return;
            }
        }

        // no more clients looking for significant wifi changes
        // no need to keep the state machine running; disable it
        mWifiChangeStateMachine.disable();