blob: 713dff8bde67d95fe2186d0b707a7e890e7e8732 [file] [log] [blame]
/*
* Copyright (C) 2008 Esmertec AG.
* Copyright (C) 2008 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.mms.util;
import android.content.BroadcastReceiver;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.database.Cursor;
import android.database.sqlite.SqliteWrapper;
import android.net.Uri;
import android.os.Handler;
import android.os.SystemProperties;
import android.preference.PreferenceManager;
import android.provider.Telephony.Mms;
import android.telephony.ServiceState;
import android.util.Log;
import android.widget.Toast;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import com.android.internal.telephony.TelephonyIntents;
import com.android.internal.telephony.TelephonyProperties;
import com.android.mms.LogTag;
import com.android.mms.R;
import com.android.mms.data.Contact;
import com.android.mms.ui.MessagingPreferenceActivity;
import com.google.android.mms.MmsException;
import com.google.android.mms.pdu.EncodedStringValue;
import com.google.android.mms.pdu.NotificationInd;
import com.google.android.mms.pdu.PduPersister;
public class DownloadManager {
private static final String TAG = LogTag.TAG;
private static final boolean DEBUG = false;
private static final boolean LOCAL_LOGV = false;
public static final int DEFERRED_MASK = 0x04;
public static final int STATE_UNKNOWN = 0x00;
public static final int STATE_UNSTARTED = 0x80;
public static final int STATE_DOWNLOADING = 0x81;
public static final int STATE_TRANSIENT_FAILURE = 0x82;
public static final int STATE_PERMANENT_FAILURE = 0x87;
public static final int STATE_PRE_DOWNLOADING = 0x88;
// TransactionService will skip downloading Mms if auto-download is off
public static final int STATE_SKIP_RETRYING = 0x89;
private final Context mContext;
private final Handler mHandler;
private final SharedPreferences mPreferences;
private boolean mAutoDownload;
private final OnSharedPreferenceChangeListener mPreferencesChangeListener =
new OnSharedPreferenceChangeListener() {
public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
if (MessagingPreferenceActivity.AUTO_RETRIEVAL.equals(key)
|| MessagingPreferenceActivity.RETRIEVAL_DURING_ROAMING.equals(key)) {
if (LOCAL_LOGV) {
Log.v(TAG, "Preferences updated.");
}
synchronized (sInstance) {
mAutoDownload = getAutoDownloadState(prefs);
if (LOCAL_LOGV) {
Log.v(TAG, "mAutoDownload ------> " + mAutoDownload);
}
}
}
}
};
private final BroadcastReceiver mRoamingStateListener =
new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (TelephonyIntents.ACTION_SERVICE_STATE_CHANGED.equals(intent.getAction())) {
if (LOCAL_LOGV) {
Log.v(TAG, "Service state changed: " + intent.getExtras());
}
ServiceState state = ServiceState.newFromBundle(intent.getExtras());
boolean isRoaming = state.getRoaming();
if (LOCAL_LOGV) {
Log.v(TAG, "roaming ------> " + isRoaming);
}
synchronized (sInstance) {
mAutoDownload = getAutoDownloadState(mPreferences, isRoaming);
if (LOCAL_LOGV) {
Log.v(TAG, "mAutoDownload ------> " + mAutoDownload);
}
}
}
}
};
private static DownloadManager sInstance;
private DownloadManager(Context context) {
mContext = context;
mHandler = new Handler();
mPreferences = PreferenceManager.getDefaultSharedPreferences(context);
mPreferences.registerOnSharedPreferenceChangeListener(mPreferencesChangeListener);
context.registerReceiver(
mRoamingStateListener,
new IntentFilter(TelephonyIntents.ACTION_SERVICE_STATE_CHANGED));
mAutoDownload = getAutoDownloadState(mPreferences);
if (LOCAL_LOGV) {
Log.v(TAG, "mAutoDownload ------> " + mAutoDownload);
}
}
public boolean isAuto() {
return mAutoDownload;
}
public static void init(Context context) {
if (LOCAL_LOGV) {
Log.v(TAG, "DownloadManager.init()");
}
if (sInstance != null) {
Log.w(TAG, "Already initialized.");
}
sInstance = new DownloadManager(context);
}
public static DownloadManager getInstance() {
if (sInstance == null) {
throw new IllegalStateException("Uninitialized.");
}
return sInstance;
}
static boolean getAutoDownloadState(SharedPreferences prefs) {
return getAutoDownloadState(prefs, isRoaming());
}
static boolean getAutoDownloadState(SharedPreferences prefs, boolean roaming) {
boolean autoDownload = prefs.getBoolean(
MessagingPreferenceActivity.AUTO_RETRIEVAL, true);
if (LOCAL_LOGV) {
Log.v(TAG, "auto download without roaming -> " + autoDownload);
}
if (autoDownload) {
boolean alwaysAuto = prefs.getBoolean(
MessagingPreferenceActivity.RETRIEVAL_DURING_ROAMING, false);
if (LOCAL_LOGV) {
Log.v(TAG, "auto download during roaming -> " + alwaysAuto);
}
if (!roaming || alwaysAuto) {
return true;
}
}
return false;
}
static boolean isRoaming() {
return isRoaming(SubscriptionManager.getDefaultSmsSubId());
}
static boolean isRoaming(int subId) {
TelephonyManager teleMgr = TelephonyManager.getDefault();
if (teleMgr == null) {
return false;
}
return teleMgr.isNetworkRoaming(subId);
}
public void markState(final Uri uri, int state) {
// Notify user if the message has expired.
try {
NotificationInd nInd = (NotificationInd) PduPersister.getPduPersister(mContext)
.load(uri);
if ((nInd.getExpiry() < System.currentTimeMillis() / 1000L)
&& (state == STATE_DOWNLOADING || state == STATE_PRE_DOWNLOADING)) {
mHandler.post(new Runnable() {
public void run() {
Toast.makeText(mContext, R.string.service_message_not_found,
Toast.LENGTH_LONG).show();
}
});
SqliteWrapper.delete(mContext, mContext.getContentResolver(), uri, null, null);
return;
}
} catch(MmsException e) {
Log.e(TAG, e.getMessage(), e);
return;
}
// Notify user if downloading permanently failed.
if (state == STATE_PERMANENT_FAILURE) {
mHandler.post(new Runnable() {
public void run() {
try {
Toast.makeText(mContext, getMessage(uri),
Toast.LENGTH_LONG).show();
} catch (MmsException e) {
Log.e(TAG, e.getMessage(), e);
}
}
});
} else if (!mAutoDownload) {
state |= DEFERRED_MASK;
}
// Use the STATUS field to store the state of downloading process
// because it's useless for M-Notification.ind.
ContentValues values = new ContentValues(1);
values.put(Mms.STATUS, state);
SqliteWrapper.update(mContext, mContext.getContentResolver(),
uri, values, null, null);
}
public void showErrorCodeToast(int errorStr) {
final int errStr = errorStr;
mHandler.post(new Runnable() {
public void run() {
try {
Toast.makeText(mContext, errStr, Toast.LENGTH_LONG).show();
} catch (Exception e) {
Log.e(TAG,"Caught an exception in showErrorCodeToast");
}
}
});
}
private String getMessage(Uri uri) throws MmsException {
NotificationInd ind = (NotificationInd) PduPersister
.getPduPersister(mContext).load(uri);
EncodedStringValue v = ind.getSubject();
String subject = (v != null) ? v.getString()
: mContext.getString(R.string.no_subject);
v = ind.getFrom();
String from = (v != null)
? Contact.get(v.getString(), false).getName()
: mContext.getString(R.string.unknown_sender);
return mContext.getString(R.string.dl_failure_notification, subject, from);
}
public int getState(Uri uri) {
Cursor cursor = SqliteWrapper.query(mContext, mContext.getContentResolver(),
uri, new String[] {Mms.STATUS}, null, null, null);
if (cursor != null) {
try {
if (cursor.moveToFirst()) {
return cursor.getInt(0) & ~DEFERRED_MASK;
}
} finally {
cursor.close();
}
}
return STATE_UNSTARTED;
}
}