1/*
2 * Copyright (C) 2016 The Android Open Source Project
3 * Copyright (C) 2016 Mopria Alliance, Inc.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 *      http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18package com.android.bips.util;
19
20import android.content.BroadcastReceiver;
21import android.content.Context;
22import android.content.Intent;
23import android.content.IntentFilter;
24import android.net.ConnectivityManager;
25import android.net.Network;
26import android.net.NetworkInfo;
27import android.util.Log;
28
29/** Reliably reports on changes to Wi-Fi connectivity state */
30public class WifiMonitor implements AutoCloseable {
31    private static final String TAG = WifiMonitor.class.getSimpleName();
32    private static final boolean DEBUG = false;
33
34    private final Context mContext;
35    private final Listener mListener;
36
37    // Current connectivity state or null if not known yet
38    private Boolean mConnected;
39
40    public interface Listener {
41        void onConnectionStateChanged(boolean isConnected);
42    }
43
44    private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
45        @Override
46        public void onReceive(Context context, Intent intent) {
47            if (ConnectivityManager.CONNECTIVITY_ACTION.equals(intent.getAction())) {
48                boolean isConnected = isConnected(context);
49                if (mConnected == null || mConnected != isConnected) {
50                    mConnected = isConnected;
51                    mListener.onConnectionStateChanged(mConnected);
52                }
53            }
54        }
55    };
56
57    /**
58     * Begin listening for connectivity changes, signalling the current WiFi
59     * connectivity state and any subsequent state changes to the listener.
60     */
61    public WifiMonitor(Context context, Listener listener) {
62        if (DEBUG) Log.d(TAG, "WifiMonitor()");
63        mListener = listener;
64        mContext = context;
65        IntentFilter filter = new IntentFilter();
66        filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
67        mContext.registerReceiver(mBroadcastReceiver, filter);
68    }
69
70    /** Return the current connectivity state */
71    public static boolean isConnected(Context context) {
72        ConnectivityManager cm =
73                (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
74
75        for (Network network : cm.getAllNetworks()) {
76            NetworkInfo networkInfo = cm.getNetworkInfo(network);
77            if (networkInfo != null && networkInfo.isConnected() &&
78                    networkInfo.getType() == ConnectivityManager.TYPE_WIFI) {
79                return true;
80            }
81        }
82        return false;
83    }
84
85    /**
86     * Stop listening for connectivity state
87     */
88    @Override
89    public void close() {
90        if (DEBUG) Log.d(TAG, "close()");
91        if (mBroadcastReceiver != null) {
92            mContext.unregisterReceiver(mBroadcastReceiver);
93            mBroadcastReceiver = null;
94        }
95    }
96
97    /** A factory for creating instances of this object (needed for unit tests) */
98    public static class Factory {
99        public WifiMonitor create(Context context, Listener listener) {
100            return new WifiMonitor(context, listener);
101        }
102    }
103}