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 */
39@Deprecated
40public class NetworkConnectivityListener {
41    private static final String TAG = "NetworkConnectivityListener";
42    private static final boolean DBG = false;
43
44    private Context mContext;
45    private HashMap<Handler, Integer> mHandlers = new HashMap<Handler, Integer>();
46    private State mState;
47    private boolean mListening;
48    private String mReason;
49    private boolean mIsFailover;
50
51    /** Network connectivity information */
52    private NetworkInfo mNetworkInfo;
53
54    /**
55     * In case of a Disconnect, the connectivity manager may have
56     * already established, or may be attempting to establish, connectivity
57     * with another network. If so, {@code mOtherNetworkInfo} will be non-null.
58     */
59    private NetworkInfo mOtherNetworkInfo;
60
61    private ConnectivityBroadcastReceiver mReceiver;
62
63    private class ConnectivityBroadcastReceiver extends BroadcastReceiver {
64        @Override
65        public void onReceive(Context context, Intent intent) {
66            String action = intent.getAction();
67
68            if (!action.equals(ConnectivityManager.CONNECTIVITY_ACTION) ||
69                mListening == false) {
70                Log.w(TAG, "onReceived() called with " + mState.toString() + " and " + intent);
71                return;
72            }
73
74            boolean noConnectivity =
75                intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, false);
76
77            if (noConnectivity) {
78                mState = State.NOT_CONNECTED;
79            } else {
80                mState = State.CONNECTED;
81            }
82
83            mNetworkInfo = (NetworkInfo)
84                intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO);
85            mOtherNetworkInfo = (NetworkInfo)
86                intent.getParcelableExtra(ConnectivityManager.EXTRA_OTHER_NETWORK_INFO);
87
88            mReason = intent.getStringExtra(ConnectivityManager.EXTRA_REASON);
89            mIsFailover =
90                intent.getBooleanExtra(ConnectivityManager.EXTRA_IS_FAILOVER, false);
91
92            if (DBG) {
93                Log.d(TAG, "onReceive(): mNetworkInfo=" + mNetworkInfo +  " mOtherNetworkInfo = "
94                        + (mOtherNetworkInfo == null ? "[none]" : mOtherNetworkInfo +
95                        " noConn=" + noConnectivity) + " mState=" + mState.toString());
96            }
97
98            // Notifiy any handlers.
99            Iterator<Handler> it = mHandlers.keySet().iterator();
100            while (it.hasNext()) {
101                Handler target = it.next();
102                Message message = Message.obtain(target, mHandlers.get(target));
103                target.sendMessage(message);
104            }
105        }
106    }
107
108    public enum State {
109        UNKNOWN,
110
111        /** This state is returned if there is connectivity to any network **/
112        CONNECTED,
113        /**
114         * This state is returned if there is no connectivity to any network. This is set
115         * to true under two circumstances:
116         * <ul>
117         * <li>When connectivity is lost to one network, and there is no other available
118         * network to attempt to switch to.</li>
119         * <li>When connectivity is lost to one network, and the attempt to switch to
120         * another network fails.</li>
121         */
122        NOT_CONNECTED
123    }
124
125    /**
126     * Create a new NetworkConnectivityListener.
127     */
128    public NetworkConnectivityListener() {
129        mState = State.UNKNOWN;
130        mReceiver = new ConnectivityBroadcastReceiver();
131    }
132
133    /**
134     * This method starts listening for network connectivity state changes.
135     * @param context
136     */
137    public synchronized void startListening(Context context) {
138        if (!mListening) {
139            mContext = context;
140
141            IntentFilter filter = new IntentFilter();
142            filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
143            context.registerReceiver(mReceiver, filter);
144            mListening = true;
145        }
146    }
147
148    /**
149     * This method stops this class from listening for network changes.
150     */
151    public synchronized void stopListening() {
152        if (mListening) {
153            mContext.unregisterReceiver(mReceiver);
154            mContext = null;
155            mNetworkInfo = null;
156            mOtherNetworkInfo = null;
157            mIsFailover = false;
158            mReason = null;
159            mListening = false;
160        }
161    }
162
163    /**
164     * This methods registers a Handler to be called back onto with the specified what code when
165     * the network connectivity state changes.
166     *
167     * @param target The target handler.
168     * @param what The what code to be used when posting a message to the handler.
169     */
170    public void registerHandler(Handler target, int what) {
171        mHandlers.put(target, what);
172    }
173
174    /**
175     * This methods unregisters the specified Handler.
176     * @param target
177     */
178    public void unregisterHandler(Handler target) {
179        mHandlers.remove(target);
180    }
181
182    public State getState() {
183        return mState;
184    }
185
186    /**
187     * Return the NetworkInfo associated with the most recent connectivity event.
188     * @return {@code NetworkInfo} for the network that had the most recent connectivity event.
189     */
190    public NetworkInfo getNetworkInfo() {
191        return mNetworkInfo;
192    }
193
194    /**
195     * If the most recent connectivity event was a DISCONNECT, return
196     * any information supplied in the broadcast about an alternate
197     * network that might be available. If this returns a non-null
198     * value, then another broadcast should follow shortly indicating
199     * whether connection to the other network succeeded.
200     *
201     * @return NetworkInfo
202     */
203    public NetworkInfo getOtherNetworkInfo() {
204        return mOtherNetworkInfo;
205    }
206
207    /**
208     * Returns true if the most recent event was for an attempt to switch over to
209     * a new network following loss of connectivity on another network.
210     * @return {@code true} if this was a failover attempt, {@code false} otherwise.
211     */
212    public boolean isFailover() {
213        return mIsFailover;
214    }
215
216    /**
217     * An optional reason for the connectivity state change may have been supplied.
218     * This returns it.
219     * @return the reason for the state change, if available, or {@code null}
220     * otherwise.
221     */
222    public String getReason() {
223        return mReason;
224    }
225}
226