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 31560bfadc3151f7a06f3b06e9a6c92cfa534c63ecScott Kennedyimport com.android.mail.utils.LogUtils; 32f419287f22ae44f25e1ba1f757ec33c7941bbfa8Marc Blank 333ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank/** 343ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank * Encapsulates functionality of ConnectivityManager for use in the Email application. In 353ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank * particular, this class provides callbacks for connectivity lost, connectivity restored, and 363ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank * background setting changed, as well as providing a method that waits for connectivity 373ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank * to be available without holding a wake lock 383ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank * 393ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank * To use, EmailConnectivityManager mgr = new EmailConnectivityManager(context, "Name"); 403ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank * When done, mgr.unregister() to unregister the internal receiver 413ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank * 423ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank * TODO: Use this class in ExchangeService 433ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank */ 443ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blankpublic class EmailConnectivityManager extends BroadcastReceiver { 458a289cb07cd577d9124411bc0b3c260baf959b9aPaul Westbrook private static final String TAG = "EmailConnectivityMgr"; 463ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank 473ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank // Loop time while waiting (stopgap in case we don't get a broadcast) 483ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank private static final int CONNECTIVITY_WAIT_TIME = 10*60*1000; 493ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank 50973702b30e8c2fb2f622f4ef37b42b3bdbd3ef17Marc Blank // Sentinel value for "no active network" 51973702b30e8c2fb2f622f4ef37b42b3bdbd3ef17Marc Blank public static final int NO_ACTIVE_NETWORK = -1; 52973702b30e8c2fb2f622f4ef37b42b3bdbd3ef17Marc Blank 533ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank // The name of this manager (used for logging) 543ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank private final String mName; 553ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank // The monitor lock we use while waiting for connectivity 563ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank private final Object mLock = new Object(); 573ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank // The instantiator's context 583ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank private final Context mContext; 593ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank // The wake lock used while running (so we don't fall asleep during execution/callbacks) 603ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank private final WakeLock mWakeLock; 613ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank private final android.net.ConnectivityManager mConnectivityManager; 623ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank 633ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank // Set when we abort waitForConnectivity() via stopWait 643ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank private boolean mStop = false; 653ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank // The thread waiting for connectivity 663ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank private Thread mWaitThread; 673ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank // Whether or not we're registered with the system connectivity manager 683ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank private boolean mRegistered = true; 693ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank 703ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank public EmailConnectivityManager(Context context, String name) { 713ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank mContext = context; 723ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank mName = name; 733ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank mConnectivityManager = 743ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE); 753ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE); 763ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, name); 773ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank mContext.registerReceiver(this, new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION)); 783ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank } 793ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank 80faf9ecc992c34de53969335f9fb403d2b17f3163Marc Blank public boolean isAutoSyncAllowed() { 81faf9ecc992c34de53969335f9fb403d2b17f3163Marc Blank return ContentResolver.getMasterSyncAutomatically(); 823ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank } 833ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank 843ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank public void stopWait() { 853ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank mStop = true; 863ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank Thread thread= mWaitThread; 873ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank if (thread != null) { 883ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank thread.interrupt(); 893ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank } 903ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank } 913ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank 923ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank /** 933ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank * Called when network connectivity has been restored; this method should be overridden by 943ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank * subclasses as necessary. NOTE: CALLED ON UI THREAD 953ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank * @param networkType as defined by ConnectivityManager 963ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank */ 973ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank public void onConnectivityRestored(int networkType) { 983ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank } 993ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank 1003ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank /** 1013ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank * Called when network connectivity has been lost; this method should be overridden by 1023ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank * subclasses as necessary. NOTE: CALLED ON UI THREAD 1033ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank * @param networkType as defined by ConnectivityManager 1043ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank */ 1053ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank public void onConnectivityLost(int networkType) { 1063ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank } 1073ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank 1083ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank public void unregister() { 1093ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank try { 1103ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank mContext.unregisterReceiver(this); 1113ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank } catch (RuntimeException e) { 1123ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank // Don't crash if we didn't register 1133ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank } finally { 1143ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank mRegistered = false; 1153ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank } 1163ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank } 1173ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank 1183ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank @Override 1193ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank public void onReceive(Context context, Intent intent) { 1203ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank if (intent.getAction().equals(ConnectivityManager.CONNECTIVITY_ACTION)) { 1213ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank Bundle extras = intent.getExtras(); 1223ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank if (extras != null) { 1233ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank NetworkInfo networkInfo = 1243ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank (NetworkInfo)extras.get(ConnectivityManager.EXTRA_NETWORK_INFO); 1253ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank if (networkInfo == null) return; 1263ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank State state = networkInfo.getState(); 1273ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank if (state == State.CONNECTED) { 1283ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank synchronized (mLock) { 1293ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank mLock.notifyAll(); 1303ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank } 1313ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank onConnectivityRestored(networkInfo.getType()); 1323ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank } else if (state == State.DISCONNECTED) { 1333ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank onConnectivityLost(networkInfo.getType()); 1343ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank } 1353ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank } 1363ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank } 1373ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank } 1383ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank 13981273dfcee3b075451860f60ee15f2aa06ba81ecMarc Blank /** 14081273dfcee3b075451860f60ee15f2aa06ba81ecMarc Blank * Request current connectivity status 14181273dfcee3b075451860f60ee15f2aa06ba81ecMarc Blank * @return whether there is connectivity at this time 14281273dfcee3b075451860f60ee15f2aa06ba81ecMarc Blank */ 14381273dfcee3b075451860f60ee15f2aa06ba81ecMarc Blank public boolean hasConnectivity() { 14481273dfcee3b075451860f60ee15f2aa06ba81ecMarc Blank NetworkInfo info = mConnectivityManager.getActiveNetworkInfo(); 14581273dfcee3b075451860f60ee15f2aa06ba81ecMarc Blank return (info != null); 14681273dfcee3b075451860f60ee15f2aa06ba81ecMarc Blank } 14781273dfcee3b075451860f60ee15f2aa06ba81ecMarc Blank 148973702b30e8c2fb2f622f4ef37b42b3bdbd3ef17Marc Blank /** 149973702b30e8c2fb2f622f4ef37b42b3bdbd3ef17Marc Blank * Get the type of the currently active data network 150973702b30e8c2fb2f622f4ef37b42b3bdbd3ef17Marc Blank * @return the type of the active network (or NO_ACTIVE_NETWORK) 151973702b30e8c2fb2f622f4ef37b42b3bdbd3ef17Marc Blank */ 152973702b30e8c2fb2f622f4ef37b42b3bdbd3ef17Marc Blank public int getActiveNetworkType() { 153973702b30e8c2fb2f622f4ef37b42b3bdbd3ef17Marc Blank return getActiveNetworkType(mConnectivityManager); 154973702b30e8c2fb2f622f4ef37b42b3bdbd3ef17Marc Blank } 155973702b30e8c2fb2f622f4ef37b42b3bdbd3ef17Marc Blank 156973702b30e8c2fb2f622f4ef37b42b3bdbd3ef17Marc Blank static public int getActiveNetworkType(Context context) { 157973702b30e8c2fb2f622f4ef37b42b3bdbd3ef17Marc Blank ConnectivityManager cm = 158973702b30e8c2fb2f622f4ef37b42b3bdbd3ef17Marc Blank (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE); 159973702b30e8c2fb2f622f4ef37b42b3bdbd3ef17Marc Blank return getActiveNetworkType(cm); 160973702b30e8c2fb2f622f4ef37b42b3bdbd3ef17Marc Blank } 161973702b30e8c2fb2f622f4ef37b42b3bdbd3ef17Marc Blank 162973702b30e8c2fb2f622f4ef37b42b3bdbd3ef17Marc Blank static public int getActiveNetworkType(ConnectivityManager cm) { 163973702b30e8c2fb2f622f4ef37b42b3bdbd3ef17Marc Blank NetworkInfo info = cm.getActiveNetworkInfo(); 164973702b30e8c2fb2f622f4ef37b42b3bdbd3ef17Marc Blank if (info == null) return NO_ACTIVE_NETWORK; 165973702b30e8c2fb2f622f4ef37b42b3bdbd3ef17Marc Blank return info.getType(); 166973702b30e8c2fb2f622f4ef37b42b3bdbd3ef17Marc Blank } 167973702b30e8c2fb2f622f4ef37b42b3bdbd3ef17Marc Blank 1683ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank public void waitForConnectivity() { 1693ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank // If we're unregistered, throw an exception 1703ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank if (!mRegistered) { 1713ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank throw new IllegalStateException("ConnectivityManager not registered"); 1723ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank } 1733ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank boolean waiting = false; 1743ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank mWaitThread = Thread.currentThread(); 1753ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank // Acquire the wait lock while we work 1763ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank mWakeLock.acquire(); 1773ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank try { 1783ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank while (!mStop) { 1793ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank NetworkInfo info = mConnectivityManager.getActiveNetworkInfo(); 1803ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank if (info != null) { 1813ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank // We're done if there's an active network 1823ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank if (waiting) { 18351c653646d14d841fbe527aee9fab7a1886338f8Martin Hibdon if (DebugUtils.DEBUG) { 184560bfadc3151f7a06f3b06e9a6c92cfa534c63ecScott Kennedy LogUtils.d(TAG, mName + ": Connectivity wait ended"); 1853ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank } 1863ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank } 1873ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank return; 1883ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank } else { 1893ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank if (!waiting) { 19051c653646d14d841fbe527aee9fab7a1886338f8Martin Hibdon if (DebugUtils.DEBUG) { 191560bfadc3151f7a06f3b06e9a6c92cfa534c63ecScott Kennedy LogUtils.d(TAG, mName + ": Connectivity waiting..."); 1923ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank } 1933ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank waiting = true; 1943ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank } 1953ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank // Wait until a network is connected (or 10 mins), but let the device sleep 1963ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank synchronized (mLock) { 1973ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank // Don't hold a lock during our wait 1983ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank mWakeLock.release(); 1993ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank try { 2003ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank mLock.wait(CONNECTIVITY_WAIT_TIME); 2013ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank } catch (InterruptedException e) { 2023ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank // This is fine; we just go around the loop again 2033ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank } 2043ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank // Get the lock back and check again for connectivity 2053ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank mWakeLock.acquire(); 2063ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank } 2073ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank } 2083ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank } 2093ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank } finally { 2103ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank // Make sure we always release the wait lock 2113ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank if (mWakeLock.isHeld()) { 2123ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank mWakeLock.release(); 2133ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank } 2143ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank mWaitThread = null; 2153ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank } 2163ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank } 2173ef8f54bae6a3e02919cfd7add7ed6bf7fdda901Marc Blank} 218