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