am 3ef8f54b
: Prefetch respects "background data" setting and waits for connectivity
* commit '3ef8f54bae6a3e02919cfd7add7ed6bf7fdda901': Prefetch respects "background data" setting and waits for connectivity
This commit is contained in:
commit
b802246f99
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.AttachmentInfo;
|
||||||
import com.android.email.Controller.ControllerService;
|
import com.android.email.Controller.ControllerService;
|
||||||
import com.android.email.Email;
|
import com.android.email.Email;
|
||||||
|
import com.android.email.EmailConnectivityManager;
|
||||||
import com.android.email.ExchangeUtils.NullEmailService;
|
import com.android.email.ExchangeUtils.NullEmailService;
|
||||||
import com.android.email.NotificationController;
|
import com.android.email.NotificationController;
|
||||||
import com.android.email.Preferences;
|
|
||||||
import com.android.email.Utility;
|
import com.android.email.Utility;
|
||||||
import com.android.email.provider.AttachmentProvider;
|
import com.android.email.provider.AttachmentProvider;
|
||||||
import com.android.email.provider.EmailContent;
|
import com.android.email.provider.EmailContent;
|
||||||
@ -91,7 +91,8 @@ public class AttachmentDownloadService extends Service implements Runnable {
|
|||||||
/*package*/ static AttachmentDownloadService sRunningService = null;
|
/*package*/ static AttachmentDownloadService sRunningService = null;
|
||||||
|
|
||||||
/*package*/ Context mContext;
|
/*package*/ Context mContext;
|
||||||
private final Preferences mPreferences;
|
private EmailConnectivityManager mConnectivityManager;
|
||||||
|
|
||||||
/*package*/ final DownloadSet mDownloadSet = new DownloadSet(new DownloadComparator());
|
/*package*/ final DownloadSet mDownloadSet = new DownloadSet(new DownloadComparator());
|
||||||
|
|
||||||
private final HashMap<Long, Class<? extends Service>> mAccountServiceMap =
|
private final HashMap<Long, Class<? extends Service>> mAccountServiceMap =
|
||||||
@ -305,6 +306,10 @@ public class AttachmentDownloadService extends Service implements Runnable {
|
|||||||
if (Email.DEBUG) {
|
if (Email.DEBUG) {
|
||||||
Log.d(TAG, "== Checking attachment queue, " + mDownloadSet.size() + " entries");
|
Log.d(TAG, "== Checking attachment queue, " + mDownloadSet.size() + " entries");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Don't run unless/until we have connectivity
|
||||||
|
mConnectivityManager.waitForConnectivity();
|
||||||
|
|
||||||
Iterator<DownloadRequest> iterator = mDownloadSet.descendingIterator();
|
Iterator<DownloadRequest> iterator = mDownloadSet.descendingIterator();
|
||||||
// First, start up any required downloads, in priority order
|
// First, start up any required downloads, in priority order
|
||||||
while (iterator.hasNext() &&
|
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
|
// Then, try opportunistic download of appropriate attachments
|
||||||
int backgroundDownloads = MAX_SIMULTANEOUS_DOWNLOADS - mDownloadsInProgress.size();
|
int backgroundDownloads = MAX_SIMULTANEOUS_DOWNLOADS - mDownloadsInProgress.size();
|
||||||
// Always leave one slot for user requested download
|
// 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
|
* Calculate the download priority of an Attachment. A priority of zero means that the
|
||||||
* attachment is not marked for download.
|
* attachment is not marked for download.
|
||||||
@ -884,6 +887,7 @@ public class AttachmentDownloadService extends Service implements Runnable {
|
|||||||
public void onCreate() {
|
public void onCreate() {
|
||||||
// Start up our service thread
|
// Start up our service thread
|
||||||
new Thread(this, "AttachmentDownloadService").start();
|
new Thread(this, "AttachmentDownloadService").start();
|
||||||
|
mConnectivityManager = new EmailConnectivityManager(this, TAG);
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public IBinder onBind(Intent intent) {
|
public IBinder onBind(Intent intent) {
|
||||||
@ -898,6 +902,7 @@ public class AttachmentDownloadService extends Service implements Runnable {
|
|||||||
kick();
|
kick();
|
||||||
}
|
}
|
||||||
sRunningService = null;
|
sRunningService = null;
|
||||||
|
mConnectivityManager.unregister();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
Loading…
Reference in New Issue
Block a user