13ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank/*
23ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank * Copyright (C) 2011 The Android Open Source Project
33ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank *
43ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank * Licensed under the Apache License, Version 2.0 (the "License");
53ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank * you may not use this file except in compliance with the License.
63ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank * You may obtain a copy of the License at
73ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank *
83ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank *      http://www.apache.org/licenses/LICENSE-2.0
93ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank *
103ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank * Unless required by applicable law or agreed to in writing, software
113ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank * distributed under the License is distributed on an "AS IS" BASIS,
123ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
133ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank * See the License for the specific language governing permissions and
143ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank * limitations under the License.
153ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank */
163ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank
173ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blankpackage com.android.email;
183ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank
193ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blankimport android.content.BroadcastReceiver;
20faf9ecc992c34de53969335f9fb403d2b17f3163Marc Blankimport android.content.ContentResolver;
213ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blankimport android.content.Context;
223ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blankimport android.content.Intent;
233ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blankimport android.content.IntentFilter;
243ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blankimport android.net.ConnectivityManager;
253ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blankimport android.net.NetworkInfo;
263ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blankimport android.net.NetworkInfo.State;
273ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blankimport android.os.Bundle;
283ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blankimport android.os.PowerManager;
293ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blankimport android.os.PowerManager.WakeLock;
303ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank
31f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blankimport com.android.email2.ui.MailActivityEmail;
32560bfadc3151f7a06f3b06e9a6c92cfa534c63ecScott Kennedyimport com.android.mail.utils.LogUtils;
33f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank
343ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank/**
353ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank * Encapsulates functionality of ConnectivityManager for use in the Email application.  In
363ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank * particular, this class provides callbacks for connectivity lost, connectivity restored, and
373ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank * background setting changed, as well as providing a method that waits for connectivity
383ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank * to be available without holding a wake lock
393ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank *
403ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank * To use, EmailConnectivityManager mgr = new EmailConnectivityManager(context, "Name");
413ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank * When done, mgr.unregister() to unregister the internal receiver
423ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank *
433ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank * TODO: Use this class in ExchangeService
443ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank */
453ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blankpublic class EmailConnectivityManager extends BroadcastReceiver {
468a289cb07cd577d9124411bc0b3c260baf959b9aPaul Westbrook    private static final String TAG = "EmailConnectivityMgr";
473ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank
483ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank    // Loop time while waiting (stopgap in case we don't get a broadcast)
493ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank    private static final int CONNECTIVITY_WAIT_TIME = 10*60*1000;
503ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank
51973702b30e8c2fb2f622f4ef37b42b3bdbd3ef17Marc Blank    // Sentinel value for "no active network"
52973702b30e8c2fb2f622f4ef37b42b3bdbd3ef17Marc Blank    public static final int NO_ACTIVE_NETWORK = -1;
53973702b30e8c2fb2f622f4ef37b42b3bdbd3ef17Marc Blank
543ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank    // The name of this manager (used for logging)
553ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank    private final String mName;
563ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank    // The monitor lock we use while waiting for connectivity
573ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank    private final Object mLock = new Object();
583ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank    // The instantiator's context
593ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank    private final Context mContext;
603ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank    // The wake lock used while running (so we don't fall asleep during execution/callbacks)
613ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank    private final WakeLock mWakeLock;
623ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank    private final android.net.ConnectivityManager mConnectivityManager;
633ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank
643ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank    // Set when we abort waitForConnectivity() via stopWait
653ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank    private boolean mStop = false;
663ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank    // The thread waiting for connectivity
673ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank    private Thread mWaitThread;
683ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank    // Whether or not we're registered with the system connectivity manager
693ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank    private boolean mRegistered = true;
703ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank
713ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank    public EmailConnectivityManager(Context context, String name)  {
723ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank        mContext = context;
733ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank        mName = name;
743ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank        mConnectivityManager =
753ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank            (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
763ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank        PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
773ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank        mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, name);
783ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank        mContext.registerReceiver(this, new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
793ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank    }
803ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank
81faf9ecc992c34de53969335f9fb403d2b17f3163Marc Blank    public boolean isAutoSyncAllowed() {
82faf9ecc992c34de53969335f9fb403d2b17f3163Marc Blank        return ContentResolver.getMasterSyncAutomatically();
833ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank    }
843ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank
853ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank    public void stopWait() {
863ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank        mStop = true;
873ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank        Thread thread= mWaitThread;
883ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank        if (thread != null) {
893ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank            thread.interrupt();
903ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank        }
913ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank    }
923ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank
933ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank    /**
943ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank     * Called when network connectivity has been restored; this method should be overridden by
953ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank     * subclasses as necessary. NOTE: CALLED ON UI THREAD
963ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank     * @param networkType as defined by ConnectivityManager
973ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank     */
983ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank    public void onConnectivityRestored(int networkType) {
993ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank    }
1003ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank
1013ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank    /**
1023ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank     * Called when network connectivity has been lost; this method should be overridden by
1033ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank     * subclasses as necessary. NOTE: CALLED ON UI THREAD
1043ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank     * @param networkType as defined by ConnectivityManager
1053ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank     */
1063ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank    public void onConnectivityLost(int networkType) {
1073ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank    }
1083ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank
1093ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank    public void unregister() {
1103ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank        try {
1113ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank            mContext.unregisterReceiver(this);
1123ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank        } catch (RuntimeException e) {
1133ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank            // Don't crash if we didn't register
1143ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank        } finally {
1153ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank            mRegistered = false;
1163ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank        }
1173ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank    }
1183ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank
1193ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank    @Override
1203ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank    public void onReceive(Context context, Intent intent) {
1213ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank        if (intent.getAction().equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
1223ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank            Bundle extras = intent.getExtras();
1233ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank            if (extras != null) {
1243ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank                NetworkInfo networkInfo =
1253ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank                    (NetworkInfo)extras.get(ConnectivityManager.EXTRA_NETWORK_INFO);
1263ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank                if (networkInfo == null) return;
1273ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank                State state = networkInfo.getState();
1283ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank                if (state == State.CONNECTED) {
1293ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank                    synchronized (mLock) {
1303ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank                        mLock.notifyAll();
1313ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank                    }
1323ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank                    onConnectivityRestored(networkInfo.getType());
1333ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank                } else if (state == State.DISCONNECTED) {
1343ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank                    onConnectivityLost(networkInfo.getType());
1353ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank                }
1363ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank            }
1373ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank        }
1383ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank    }
1393ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank
14081273dfcee3b075451860f60ee15f2aa06ba81ecMarc Blank    /**
14181273dfcee3b075451860f60ee15f2aa06ba81ecMarc Blank     * Request current connectivity status
14281273dfcee3b075451860f60ee15f2aa06ba81ecMarc Blank     * @return whether there is connectivity at this time
14381273dfcee3b075451860f60ee15f2aa06ba81ecMarc Blank     */
14481273dfcee3b075451860f60ee15f2aa06ba81ecMarc Blank    public boolean hasConnectivity() {
14581273dfcee3b075451860f60ee15f2aa06ba81ecMarc Blank        NetworkInfo info = mConnectivityManager.getActiveNetworkInfo();
14681273dfcee3b075451860f60ee15f2aa06ba81ecMarc Blank        return (info != null);
14781273dfcee3b075451860f60ee15f2aa06ba81ecMarc Blank    }
14881273dfcee3b075451860f60ee15f2aa06ba81ecMarc Blank
149973702b30e8c2fb2f622f4ef37b42b3bdbd3ef17Marc Blank    /**
150973702b30e8c2fb2f622f4ef37b42b3bdbd3ef17Marc Blank     * Get the type of the currently active data network
151973702b30e8c2fb2f622f4ef37b42b3bdbd3ef17Marc Blank     * @return the type of the active network (or NO_ACTIVE_NETWORK)
152973702b30e8c2fb2f622f4ef37b42b3bdbd3ef17Marc Blank     */
153973702b30e8c2fb2f622f4ef37b42b3bdbd3ef17Marc Blank    public int getActiveNetworkType() {
154973702b30e8c2fb2f622f4ef37b42b3bdbd3ef17Marc Blank        return getActiveNetworkType(mConnectivityManager);
155973702b30e8c2fb2f622f4ef37b42b3bdbd3ef17Marc Blank    }
156973702b30e8c2fb2f622f4ef37b42b3bdbd3ef17Marc Blank
157973702b30e8c2fb2f622f4ef37b42b3bdbd3ef17Marc Blank    static public int getActiveNetworkType(Context context) {
158973702b30e8c2fb2f622f4ef37b42b3bdbd3ef17Marc Blank        ConnectivityManager cm =
159973702b30e8c2fb2f622f4ef37b42b3bdbd3ef17Marc Blank            (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
160973702b30e8c2fb2f622f4ef37b42b3bdbd3ef17Marc Blank        return getActiveNetworkType(cm);
161973702b30e8c2fb2f622f4ef37b42b3bdbd3ef17Marc Blank    }
162973702b30e8c2fb2f622f4ef37b42b3bdbd3ef17Marc Blank
163973702b30e8c2fb2f622f4ef37b42b3bdbd3ef17Marc Blank    static public int getActiveNetworkType(ConnectivityManager cm) {
164973702b30e8c2fb2f622f4ef37b42b3bdbd3ef17Marc Blank        NetworkInfo info = cm.getActiveNetworkInfo();
165973702b30e8c2fb2f622f4ef37b42b3bdbd3ef17Marc Blank        if (info == null) return NO_ACTIVE_NETWORK;
166973702b30e8c2fb2f622f4ef37b42b3bdbd3ef17Marc Blank        return info.getType();
167973702b30e8c2fb2f622f4ef37b42b3bdbd3ef17Marc Blank    }
168973702b30e8c2fb2f622f4ef37b42b3bdbd3ef17Marc Blank
1693ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank    public void waitForConnectivity() {
1703ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank        // If we're unregistered, throw an exception
1713ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank        if (!mRegistered) {
1723ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank            throw new IllegalStateException("ConnectivityManager not registered");
1733ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank        }
1743ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank        boolean waiting = false;
1753ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank        mWaitThread = Thread.currentThread();
1763ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank        // Acquire the wait lock while we work
1773ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank        mWakeLock.acquire();
1783ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank        try {
1793ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank            while (!mStop) {
1803ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank                NetworkInfo info = mConnectivityManager.getActiveNetworkInfo();
1813ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank                if (info != null) {
1823ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank                    // We're done if there's an active network
1833ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank                    if (waiting) {
184f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank                        if (MailActivityEmail.DEBUG) {
185560bfadc3151f7a06f3b06e9a6c92cfa534c63ecScott Kennedy                            LogUtils.d(TAG, mName + ": Connectivity wait ended");
1863ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank                        }
1873ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank                    }
1883ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank                    return;
1893ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank                } else {
1903ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank                    if (!waiting) {
191f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank                        if (MailActivityEmail.DEBUG) {
192560bfadc3151f7a06f3b06e9a6c92cfa534c63ecScott Kennedy                            LogUtils.d(TAG, mName + ": Connectivity waiting...");
1933ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank                        }
1943ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank                        waiting = true;
1953ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank                    }
1963ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank                    // Wait until a network is connected (or 10 mins), but let the device sleep
1973ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank                    synchronized (mLock) {
1983ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank                        // Don't hold a lock during our wait
1993ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank                        mWakeLock.release();
2003ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank                        try {
2013ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank                            mLock.wait(CONNECTIVITY_WAIT_TIME);
2023ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank                        } catch (InterruptedException e) {
2033ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank                            // This is fine; we just go around the loop again
2043ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank                        }
2053ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank                        // Get the lock back and check again for connectivity
2063ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank                        mWakeLock.acquire();
2073ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank                    }
2083ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank                }
2093ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank            }
2103ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank        } finally {
2113ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank            // Make sure we always release the wait lock
2123ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank            if (mWakeLock.isHeld()) {
2133ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank                mWakeLock.release();
2143ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank            }
2153ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank            mWaitThread = null;
2163ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank        }
2173ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank    }
2183ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank}
219