Prefetch respects "background data" setting and waits for connectivity
Bug: 3384997 Bug: 3384994 Change-Id: Id8338650b69666f2996837324e27c2e98c9261fe
This commit is contained in:
parent
48be275bbb
commit
3ef8f54bae
194
src/com/android/email/EmailConnectivityManager.java
Normal file
194
src/com/android/email/EmailConnectivityManager.java
Normal file
@ -0,0 +1,194 @@
|
||||
/*
|
||||
* Copyright (C) 2011 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.email;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.NetworkInfo;
|
||||
import android.net.NetworkInfo.State;
|
||||
import android.os.Bundle;
|
||||
import android.os.PowerManager;
|
||||
import android.os.PowerManager.WakeLock;
|
||||
import android.util.Log;
|
||||
|
||||
/**
|
||||
* Encapsulates functionality of ConnectivityManager for use in the Email application. In
|
||||
* particular, this class provides callbacks for connectivity lost, connectivity restored, and
|
||||
* background setting changed, as well as providing a method that waits for connectivity
|
||||
* to be available without holding a wake lock
|
||||
*
|
||||
* To use, EmailConnectivityManager mgr = new EmailConnectivityManager(context, "Name");
|
||||
* When done, mgr.unregister() to unregister the internal receiver
|
||||
*
|
||||
* TODO: Use this class in ExchangeService
|
||||
*/
|
||||
public class EmailConnectivityManager extends BroadcastReceiver {
|
||||
private static final String TAG = "EmailConnectivityManager";
|
||||
|
||||
// Loop time while waiting (stopgap in case we don't get a broadcast)
|
||||
private static final int CONNECTIVITY_WAIT_TIME = 10*60*1000;
|
||||
|
||||
// The name of this manager (used for logging)
|
||||
private final String mName;
|
||||
// The monitor lock we use while waiting for connectivity
|
||||
private final Object mLock = new Object();
|
||||
// The instantiator's context
|
||||
private final Context mContext;
|
||||
// The wake lock used while running (so we don't fall asleep during execution/callbacks)
|
||||
private final WakeLock mWakeLock;
|
||||
private final android.net.ConnectivityManager mConnectivityManager;
|
||||
|
||||
// Set when we abort waitForConnectivity() via stopWait
|
||||
private boolean mStop = false;
|
||||
// The thread waiting for connectivity
|
||||
private Thread mWaitThread;
|
||||
// Whether or not we're registered with the system connectivity manager
|
||||
private boolean mRegistered = true;
|
||||
|
||||
public EmailConnectivityManager(Context context, String name) {
|
||||
mContext = context;
|
||||
mName = name;
|
||||
mConnectivityManager =
|
||||
(ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||
PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
|
||||
mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, name);
|
||||
mContext.registerReceiver(this, new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
|
||||
}
|
||||
|
||||
public boolean isBackgroundDataAllowed() {
|
||||
return mConnectivityManager.getBackgroundDataSetting();
|
||||
}
|
||||
|
||||
public void stopWait() {
|
||||
mStop = true;
|
||||
Thread thread= mWaitThread;
|
||||
if (thread != null) {
|
||||
thread.interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when network connectivity has been restored; this method should be overridden by
|
||||
* subclasses as necessary. NOTE: CALLED ON UI THREAD
|
||||
* @param networkType as defined by ConnectivityManager
|
||||
*/
|
||||
public void onConnectivityRestored(int networkType) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when network connectivity has been lost; this method should be overridden by
|
||||
* subclasses as necessary. NOTE: CALLED ON UI THREAD
|
||||
* @param networkType as defined by ConnectivityManager
|
||||
*/
|
||||
public void onConnectivityLost(int networkType) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the user changes the state of the "Background Data" setting; this method should
|
||||
* be overridden by subclasses as necessary. NOTE: CALLED ON UI THREAD
|
||||
* @param state the new state of the "Background Data" setting
|
||||
*/
|
||||
public void onBackgroundDataChanged(boolean state) {
|
||||
}
|
||||
|
||||
public void unregister() {
|
||||
try {
|
||||
mContext.unregisterReceiver(this);
|
||||
} catch (RuntimeException e) {
|
||||
// Don't crash if we didn't register
|
||||
} finally {
|
||||
mRegistered = false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
if (intent.getAction().equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
|
||||
Bundle extras = intent.getExtras();
|
||||
if (extras != null) {
|
||||
NetworkInfo networkInfo =
|
||||
(NetworkInfo)extras.get(ConnectivityManager.EXTRA_NETWORK_INFO);
|
||||
if (networkInfo == null) return;
|
||||
State state = networkInfo.getState();
|
||||
if (state == State.CONNECTED) {
|
||||
synchronized (mLock) {
|
||||
mLock.notifyAll();
|
||||
}
|
||||
onConnectivityRestored(networkInfo.getType());
|
||||
} else if (state == State.DISCONNECTED) {
|
||||
onConnectivityLost(networkInfo.getType());
|
||||
}
|
||||
}
|
||||
} else if (intent.getAction().equals(
|
||||
ConnectivityManager.ACTION_BACKGROUND_DATA_SETTING_CHANGED)) {
|
||||
onBackgroundDataChanged(isBackgroundDataAllowed());
|
||||
}
|
||||
}
|
||||
|
||||
public void waitForConnectivity() {
|
||||
// If we're unregistered, throw an exception
|
||||
if (!mRegistered) {
|
||||
throw new IllegalStateException("ConnectivityManager not registered");
|
||||
}
|
||||
boolean waiting = false;
|
||||
mWaitThread = Thread.currentThread();
|
||||
// Acquire the wait lock while we work
|
||||
mWakeLock.acquire();
|
||||
try {
|
||||
while (!mStop) {
|
||||
NetworkInfo info = mConnectivityManager.getActiveNetworkInfo();
|
||||
if (info != null) {
|
||||
// We're done if there's an active network
|
||||
if (waiting) {
|
||||
if (Email.DEBUG) {
|
||||
Log.d(TAG, mName + ": Connectivity wait ended");
|
||||
}
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
if (!waiting) {
|
||||
if (Email.DEBUG) {
|
||||
Log.d(TAG, mName + ": Connectivity waiting...");
|
||||
}
|
||||
waiting = true;
|
||||
}
|
||||
// Wait until a network is connected (or 10 mins), but let the device sleep
|
||||
synchronized (mLock) {
|
||||
// Don't hold a lock during our wait
|
||||
mWakeLock.release();
|
||||
try {
|
||||
mLock.wait(CONNECTIVITY_WAIT_TIME);
|
||||
} catch (InterruptedException e) {
|
||||
// This is fine; we just go around the loop again
|
||||
}
|
||||
// Get the lock back and check again for connectivity
|
||||
mWakeLock.acquire();
|
||||
}
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
// Make sure we always release the wait lock
|
||||
if (mWakeLock.isHeld()) {
|
||||
mWakeLock.release();
|
||||
}
|
||||
mWaitThread = null;
|
||||
}
|
||||
}
|
||||
}
|
@ -19,9 +19,9 @@ package com.android.email.service;
|
||||
import com.android.email.AttachmentInfo;
|
||||
import com.android.email.Controller.ControllerService;
|
||||
import com.android.email.Email;
|
||||
import com.android.email.EmailConnectivityManager;
|
||||
import com.android.email.ExchangeUtils.NullEmailService;
|
||||
import com.android.email.NotificationController;
|
||||
import com.android.email.Preferences;
|
||||
import com.android.email.Utility;
|
||||
import com.android.email.provider.AttachmentProvider;
|
||||
import com.android.email.provider.EmailContent;
|
||||
@ -91,7 +91,8 @@ public class AttachmentDownloadService extends Service implements Runnable {
|
||||
/*package*/ static AttachmentDownloadService sRunningService = null;
|
||||
|
||||
/*package*/ Context mContext;
|
||||
private final Preferences mPreferences;
|
||||
private EmailConnectivityManager mConnectivityManager;
|
||||
|
||||
/*package*/ final DownloadSet mDownloadSet = new DownloadSet(new DownloadComparator());
|
||||
|
||||
private final HashMap<Long, Class<? extends Service>> mAccountServiceMap =
|
||||
@ -305,6 +306,10 @@ public class AttachmentDownloadService extends Service implements Runnable {
|
||||
if (Email.DEBUG) {
|
||||
Log.d(TAG, "== Checking attachment queue, " + mDownloadSet.size() + " entries");
|
||||
}
|
||||
|
||||
// Don't run unless/until we have connectivity
|
||||
mConnectivityManager.waitForConnectivity();
|
||||
|
||||
Iterator<DownloadRequest> iterator = mDownloadSet.descendingIterator();
|
||||
// First, start up any required downloads, in priority order
|
||||
while (iterator.hasNext() &&
|
||||
@ -324,6 +329,8 @@ public class AttachmentDownloadService extends Service implements Runnable {
|
||||
}
|
||||
}
|
||||
|
||||
// Don't prefetch if background downloading is disallowed
|
||||
if (!mConnectivityManager.isBackgroundDataAllowed()) return;
|
||||
// Then, try opportunistic download of appropriate attachments
|
||||
int backgroundDownloads = MAX_SIMULTANEOUS_DOWNLOADS - mDownloadsInProgress.size();
|
||||
// Always leave one slot for user requested download
|
||||
@ -582,10 +589,6 @@ public class AttachmentDownloadService extends Service implements Runnable {
|
||||
}
|
||||
}
|
||||
|
||||
public AttachmentDownloadService() {
|
||||
mPreferences = Preferences.getPreferences(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the download priority of an Attachment. A priority of zero means that the
|
||||
* attachment is not marked for download.
|
||||
@ -884,6 +887,7 @@ public class AttachmentDownloadService extends Service implements Runnable {
|
||||
public void onCreate() {
|
||||
// Start up our service thread
|
||||
new Thread(this, "AttachmentDownloadService").start();
|
||||
mConnectivityManager = new EmailConnectivityManager(this, TAG);
|
||||
}
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
@ -898,6 +902,7 @@ public class AttachmentDownloadService extends Service implements Runnable {
|
||||
kick();
|
||||
}
|
||||
sRunningService = null;
|
||||
mConnectivityManager.unregister();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
Loading…
Reference in New Issue
Block a user