1/*
2 * Copyright (C) 2006 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.common;
18
19import android.content.BroadcastReceiver;
20import android.content.Context;
21import android.content.Intent;
22import android.content.IntentFilter;
23import android.net.ConnectivityManager;
24import android.net.NetworkInfo;
25import android.os.Handler;
26import android.os.Message;
27import android.util.Log;
28
29import java.util.HashMap;
30import java.util.Iterator;
31
32/**
33 * A wrapper for a broadcast receiver that provides network connectivity
34 * state information, independent of network type (mobile, Wi-Fi, etc.).
35 * @deprecated Code tempted to use this class should simply listen for connectivity intents
36 * (or poll ConnectivityManager) directly.
37 * {@hide}
38 */
39public class NetworkConnectivityListener {
40    private static final String TAG = "NetworkConnectivityListener";
41    private static final boolean DBG = false;
42
43    private Context mContext;
44    private HashMap<Handler, Integer> mHandlers = new HashMap<Handler, Integer>();
45    private State mState;
46    private boolean mListening;
47    private String mReason;
48    private boolean mIsFailover;
49
50    /** Network connectivity information */
51    private NetworkInfo mNetworkInfo;
52
53    /**
54     * In case of a Disconnect, the connectivity manager may have
55     * already established, or may be attempting to establish, connectivity
56     * with another network. If so, {@code mOtherNetworkInfo} will be non-null.
57     */
58    private NetworkInfo mOtherNetworkInfo;
59
60    private ConnectivityBroadcastReceiver mReceiver;
61
62    private class ConnectivityBroadcastReceiver extends BroadcastReceiver {
63        @Override
64        public void onReceive(Context context, Intent intent) {
65            String action = intent.getAction();
66
67            if (!action.equals(ConnectivityManager.CONNECTIVITY_ACTION) ||
68                mListening == false) {
69                Log.w(TAG, "onReceived() called with " + mState.toString() + " and " + intent);
70                return;
71            }
72
73            boolean noConnectivity =
74                intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, false);
75
76            if (noConnectivity) {
77                mState = State.NOT_CONNECTED;
78            } else {
79                mState = State.CONNECTED;
80            }
81
82            mNetworkInfo = (NetworkInfo)
83                intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO);
84            mOtherNetworkInfo = (NetworkInfo)
85                intent.getParcelableExtra(ConnectivityManager.EXTRA_OTHER_NETWORK_INFO);
86
87            mReason = intent.getStringExtra(ConnectivityManager.EXTRA_REASON);
88            mIsFailover =
89                intent.getBooleanExtra(ConnectivityManager.EXTRA_IS_FAILOVER, false);
90
91            if (DBG) {
92                Log.d(TAG, "onReceive(): mNetworkInfo=" + mNetworkInfo +  " mOtherNetworkInfo = "
93                        + (mOtherNetworkInfo == null ? "[none]" : mOtherNetworkInfo +
94                        " noConn=" + noConnectivity) + " mState=" + mState.toString());
95            }
96
97            // Notifiy any handlers.
98            Iterator<Handler> it = mHandlers.keySet().iterator();
99            while (it.hasNext()) {
100                Handler target = it.next();
101                Message message = Message.obtain(target, mHandlers.get(target));
102                target.sendMessage(message);
103            }
104        }
105    };
106
107    public enum State {
108        UNKNOWN,
109
110        /** This state is returned if there is connectivity to any network **/
111        CONNECTED,
112        /**
113         * This state is returned if there is no connectivity to any network. This is set
114         * to true under two circumstances:
115         * <ul>
116         * <li>When connectivity is lost to one network, and there is no other available
117         * network to attempt to switch to.</li>
118         * <li>When connectivity is lost to one network, and the attempt to switch to
119         * another network fails.</li>
120         */
121        NOT_CONNECTED
122    }
123
124    /**
125     * Create a new NetworkConnectivityListener.
126     */
127    public NetworkConnectivityListener() {
128        mState = State.UNKNOWN;
129        mReceiver = new ConnectivityBroadcastReceiver();
130    }
131
132    /**
133     * This method starts listening for network connectivity state changes.
134     * @param context
135     */
136    public synchronized void startListening(Context context) {
137        if (!mListening) {
138            mContext = context;
139
140            IntentFilter filter = new IntentFilter();
141            filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
142            context.registerReceiver(mReceiver, filter);
143            mListening = true;
144        }
145    }
146
147    /**
148     * This method stops this class from listening for network changes.
149     */
150    public synchronized void stopListening() {
151        if (mListening) {
152            mContext.unregisterReceiver(mReceiver);
153            mContext = null;
154            mNetworkInfo = null;
155            mOtherNetworkInfo = null;
156            mIsFailover = false;
157            mReason = null;
158            mListening = false;
159        }
160    }
161
162    /**
163     * This methods registers a Handler to be called back onto with the specified what code when
164     * the network connectivity state changes.
165     *
166     * @param target The target handler.
167     * @param what The what code to be used when posting a message to the handler.
168     */
169    public void registerHandler(Handler target, int what) {
170        mHandlers.put(target, what);
171    }
172
173    /**
174     * This methods unregisters the specified Handler.
175     * @param target
176     */
177    public void unregisterHandler(Handler target) {
178        mHandlers.remove(target);
179    }
180
181    public State getState() {
182        return mState;
183    }
184
185    /**
186     * Return the NetworkInfo associated with the most recent connectivity event.
187     * @return {@code NetworkInfo} for the network that had the most recent connectivity event.
188     */
189    public NetworkInfo getNetworkInfo() {
190        return mNetworkInfo;
191    }
192
193    /**
194     * If the most recent connectivity event was a DISCONNECT, return
195     * any information supplied in the broadcast about an alternate
196     * network that might be available. If this returns a non-null
197     * value, then another broadcast should follow shortly indicating
198     * whether connection to the other network succeeded.
199     *
200     * @return NetworkInfo
201     */
202    public NetworkInfo getOtherNetworkInfo() {
203        return mOtherNetworkInfo;
204    }
205
206    /**
207     * Returns true if the most recent event was for an attempt to switch over to
208     * a new network following loss of connectivity on another network.
209     * @return {@code true} if this was a failover attempt, {@code false} otherwise.
210     */
211    public boolean isFailover() {
212        return mIsFailover;
213    }
214
215    /**
216     * An optional reason for the connectivity state change may have been supplied.
217     * This returns it.
218     * @return the reason for the state change, if available, or {@code null}
219     * otherwise.
220     */
221    public String getReason() {
222        return mReason;
223    }
224}
225