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

WifiNotificationController

public final class WifiNotificationController extends Object

Fields Summary
private static final int
ICON_NETWORKS_AVAILABLE
The icon to show in the 'available networks' notification. This will also be the ID of the Notification given to the NotificationManager.
private final long
NOTIFICATION_REPEAT_DELAY_MS
When a notification is shown, we wait this amount before possibly showing it again.
private boolean
mNotificationEnabled
Whether the user has set the setting to show the 'available networks' notification.
private NotificationEnabledSettingObserver
mNotificationEnabledSettingObserver
Observes the user setting to keep {@link #mNotificationEnabled} in sync.
private long
mNotificationRepeatTime
The {@link System#currentTimeMillis()} must be at least this value for us to show the notification again.
private android.app.Notification
mNotification
The Notification object given to the NotificationManager.
private boolean
mNotificationShown
Whether the notification is being shown, as set by us. That is, if the user cancels the notification, we will not receive the callback so this will still be true. We only guarantee if this is false, then the notification is not showing.
private static final int
NUM_SCANS_BEFORE_ACTUALLY_SCANNING
The number of continuous scans that must occur before consider the supplicant in a scanning state. This allows supplicant to associate with remembered networks that are in the scan results.
private int
mNumScansSinceNetworkStateChange
The number of scans since the last network state change. When this exceeds {@link #NUM_SCANS_BEFORE_ACTUALLY_SCANNING}, we consider the supplicant to actually be scanning. When the network state changes to something other than scanning, we reset this to 0.
private final android.content.Context
mContext
private final WifiStateMachine
mWifiStateMachine
private android.net.NetworkInfo
mNetworkInfo
private volatile int
mWifiState
Constructors Summary
WifiNotificationController(android.content.Context context, WifiStateMachine wsm)


        
        mContext = context;
        mWifiStateMachine = wsm;
        mWifiState = WifiManager.WIFI_STATE_UNKNOWN;

        IntentFilter filter = new IntentFilter();
        filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
        filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
        filter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);

        mContext.registerReceiver(
                new BroadcastReceiver() {
                    @Override
                    public void onReceive(Context context, Intent intent) {
                        if (intent.getAction().equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {
                            mWifiState = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
                                    WifiManager.WIFI_STATE_UNKNOWN);
                            resetNotification();
                        } else if (intent.getAction().equals(
                                WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
                            mNetworkInfo = (NetworkInfo) intent.getParcelableExtra(
                                    WifiManager.EXTRA_NETWORK_INFO);
                            // reset & clear notification on a network connect & disconnect
                            switch(mNetworkInfo.getDetailedState()) {
                                case CONNECTED:
                                case DISCONNECTED:
                                case CAPTIVE_PORTAL_CHECK:
                                    resetNotification();
                                    break;
                            }
                        } else if (intent.getAction().equals(
                                WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) {
                            checkAndSetNotification(mNetworkInfo,
                                    mWifiStateMachine.syncGetScanResultsList());
                        }
                    }
                }, filter);

        // Setting is in seconds
        NOTIFICATION_REPEAT_DELAY_MS = Settings.Global.getInt(context.getContentResolver(),
                Settings.Global.WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY, 900) * 1000l;
        mNotificationEnabledSettingObserver = new NotificationEnabledSettingObserver(new Handler());
        mNotificationEnabledSettingObserver.register();
    
Methods Summary
private synchronized voidcheckAndSetNotification(android.net.NetworkInfo networkInfo, java.util.List scanResults)


        // TODO: unregister broadcast so we do not have to check here
        // If we shouldn't place a notification on available networks, then
        // don't bother doing any of the following
        if (!mNotificationEnabled) return;
        if (mWifiState != WifiManager.WIFI_STATE_ENABLED) return;

        NetworkInfo.State state = NetworkInfo.State.DISCONNECTED;
        if (networkInfo != null)
            state = networkInfo.getState();

        if ((state == NetworkInfo.State.DISCONNECTED)
                || (state == NetworkInfo.State.UNKNOWN)) {
            if (scanResults != null) {
                int numOpenNetworks = 0;
                for (int i = scanResults.size() - 1; i >= 0; i--) {
                    ScanResult scanResult = scanResults.get(i);

                    //A capability of [ESS] represents an open access point
                    //that is available for an STA to connect
                    if (scanResult.capabilities != null &&
                            scanResult.capabilities.equals("[ESS]")) {
                        numOpenNetworks++;
                    }
                }

                if (numOpenNetworks > 0) {
                    if (++mNumScansSinceNetworkStateChange >= NUM_SCANS_BEFORE_ACTUALLY_SCANNING) {
                        /*
                         * We've scanned continuously at least
                         * NUM_SCANS_BEFORE_NOTIFICATION times. The user
                         * probably does not have a remembered network in range,
                         * since otherwise supplicant would have tried to
                         * associate and thus resetting this counter.
                         */
                        setNotificationVisible(true, numOpenNetworks, false, 0);
                    }
                    return;
                }
            }
        }

        // No open networks in range, remove the notification
        setNotificationVisible(false, 0, false, 0);
    
voiddump(java.io.FileDescriptor fd, java.io.PrintWriter pw, java.lang.String[] args)

        pw.println("mNotificationEnabled " + mNotificationEnabled);
        pw.println("mNotificationRepeatTime " + mNotificationRepeatTime);
        pw.println("mNotificationShown " + mNotificationShown);
        pw.println("mNumScansSinceNetworkStateChange " + mNumScansSinceNetworkStateChange);
    
private synchronized voidresetNotification()
Clears variables related to tracking whether a notification has been shown recently and clears the current notification.

        mNotificationRepeatTime = 0;
        mNumScansSinceNetworkStateChange = 0;
        setNotificationVisible(false, 0, false, 0);
    
private voidsetNotificationVisible(boolean visible, int numNetworks, boolean force, int delay)
Display or don't display a notification that there are open Wi-Fi networks.

param
visible {@code true} if notification should be visible, {@code false} otherwise
param
numNetworks the number networks seen
param
force {@code true} to force notification to be shown/not-shown, even if it is already shown/not-shown.
param
delay time in milliseconds after which the notification should be made visible or invisible.


        // Since we use auto cancel on the notification, when the
        // mNetworksAvailableNotificationShown is true, the notification may
        // have actually been canceled.  However, when it is false we know
        // for sure that it is not being shown (it will not be shown any other
        // place than here)

        // If it should be hidden and it is already hidden, then noop
        if (!visible && !mNotificationShown && !force) {
            return;
        }

        NotificationManager notificationManager = (NotificationManager) mContext
                .getSystemService(Context.NOTIFICATION_SERVICE);

        Message message;
        if (visible) {

            // Not enough time has passed to show the notification again
            if (System.currentTimeMillis() < mNotificationRepeatTime) {
                return;
            }

            if (mNotification == null) {
                // Cache the Notification object.
                mNotification = new Notification();
                mNotification.when = 0;
                mNotification.icon = ICON_NETWORKS_AVAILABLE;
                mNotification.flags = Notification.FLAG_AUTO_CANCEL;
                mNotification.contentIntent = TaskStackBuilder.create(mContext)
                        .addNextIntentWithParentStack(
                                new Intent(WifiManager.ACTION_PICK_WIFI_NETWORK))
                        .getPendingIntent(0, 0, null, UserHandle.CURRENT);
            }

            CharSequence title = mContext.getResources().getQuantityText(
                    com.android.internal.R.plurals.wifi_available, numNetworks);
            CharSequence details = mContext.getResources().getQuantityText(
                    com.android.internal.R.plurals.wifi_available_detailed, numNetworks);
            mNotification.tickerText = title;
            mNotification.color = mContext.getResources().getColor(
                    com.android.internal.R.color.system_notification_accent_color);
            mNotification.setLatestEventInfo(mContext, title, details, mNotification.contentIntent);

            mNotificationRepeatTime = System.currentTimeMillis() + NOTIFICATION_REPEAT_DELAY_MS;

            notificationManager.notifyAsUser(null, ICON_NETWORKS_AVAILABLE, mNotification,
                    UserHandle.ALL);
        } else {
            notificationManager.cancelAsUser(null, ICON_NETWORKS_AVAILABLE, UserHandle.ALL);
        }

        mNotificationShown = visible;