DownloadManager.java revision 66dde9460badebf8e740275cabde9cca256006eb
1cd0189299f484dcbd51400b994daf585923e9e8dDavid Krause/* 2cd0189299f484dcbd51400b994daf585923e9e8dDavid Krause * Copyright (C) 2008 Esmertec AG. 3cd0189299f484dcbd51400b994daf585923e9e8dDavid Krause * Copyright (C) 2008 The Android Open Source Project 4cd0189299f484dcbd51400b994daf585923e9e8dDavid Krause * 5cd0189299f484dcbd51400b994daf585923e9e8dDavid Krause * Licensed under the Apache License, Version 2.0 (the "License"); 6cd0189299f484dcbd51400b994daf585923e9e8dDavid Krause * you may not use this file except in compliance with the License. 7cd0189299f484dcbd51400b994daf585923e9e8dDavid Krause * You may obtain a copy of the License at 8849bc5bfd940cea4e55332e805e0a7da4a765bcdDmitri Plotnikov * 9cd0189299f484dcbd51400b994daf585923e9e8dDavid Krause * http://www.apache.org/licenses/LICENSE-2.0 10cd0189299f484dcbd51400b994daf585923e9e8dDavid Krause * 114a0b3738f8a710d2ffc8c49b3ae7e44100c88839Tim Park * Unless required by applicable law or agreed to in writing, software 124a0b3738f8a710d2ffc8c49b3ae7e44100c88839Tim Park * distributed under the License is distributed on an "AS IS" BASIS, 134a0b3738f8a710d2ffc8c49b3ae7e44100c88839Tim Park * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 144a0b3738f8a710d2ffc8c49b3ae7e44100c88839Tim Park * See the License for the specific language governing permissions and 154a0b3738f8a710d2ffc8c49b3ae7e44100c88839Tim Park * limitations under the License. 16cd0189299f484dcbd51400b994daf585923e9e8dDavid Krause */ 17cd0189299f484dcbd51400b994daf585923e9e8dDavid Krause 18cd0189299f484dcbd51400b994daf585923e9e8dDavid Krausepackage com.android.mms.util; 19cd0189299f484dcbd51400b994daf585923e9e8dDavid Krause 20cd0189299f484dcbd51400b994daf585923e9e8dDavid Krauseimport com.android.internal.telephony.TelephonyIntents; 21849bc5bfd940cea4e55332e805e0a7da4a765bcdDmitri Plotnikovimport com.android.internal.telephony.TelephonyProperties; 22cd0189299f484dcbd51400b994daf585923e9e8dDavid Krauseimport com.android.mms.R; 23cd0189299f484dcbd51400b994daf585923e9e8dDavid Krauseimport com.android.mms.ui.MessagingPreferenceActivity; 24cd0189299f484dcbd51400b994daf585923e9e8dDavid Krauseimport com.google.android.mms.MmsException; 25cd0189299f484dcbd51400b994daf585923e9e8dDavid Krauseimport com.google.android.mms.pdu.EncodedStringValue; 26cd0189299f484dcbd51400b994daf585923e9e8dDavid Krauseimport com.google.android.mms.pdu.NotificationInd; 27cd0189299f484dcbd51400b994daf585923e9e8dDavid Krauseimport com.google.android.mms.pdu.PduPersister; 28cd0189299f484dcbd51400b994daf585923e9e8dDavid Krauseimport com.google.android.mms.util.SqliteWrapper; 29cd0189299f484dcbd51400b994daf585923e9e8dDavid Krause 30cd0189299f484dcbd51400b994daf585923e9e8dDavid Krauseimport android.content.BroadcastReceiver; 31cd0189299f484dcbd51400b994daf585923e9e8dDavid Krauseimport android.content.ContentValues; 32cd0189299f484dcbd51400b994daf585923e9e8dDavid Krauseimport android.content.Context; 33cd0189299f484dcbd51400b994daf585923e9e8dDavid Krauseimport android.content.Intent; 34cd0189299f484dcbd51400b994daf585923e9e8dDavid Krauseimport android.content.IntentFilter; 35cd0189299f484dcbd51400b994daf585923e9e8dDavid Krauseimport android.content.SharedPreferences; 36cd0189299f484dcbd51400b994daf585923e9e8dDavid Krauseimport android.content.SharedPreferences.OnSharedPreferenceChangeListener; 374a0b3738f8a710d2ffc8c49b3ae7e44100c88839Tim Parkimport android.database.Cursor; 38cd0189299f484dcbd51400b994daf585923e9e8dDavid Krauseimport android.net.Uri; 39cd0189299f484dcbd51400b994daf585923e9e8dDavid Krauseimport android.os.Handler; 404a0b3738f8a710d2ffc8c49b3ae7e44100c88839Tim Parkimport android.os.SystemProperties; 414a0b3738f8a710d2ffc8c49b3ae7e44100c88839Tim Parkimport android.preference.PreferenceManager; 424a0b3738f8a710d2ffc8c49b3ae7e44100c88839Tim Parkimport android.provider.Telephony.Mms; 434a0b3738f8a710d2ffc8c49b3ae7e44100c88839Tim Parkimport android.telephony.ServiceState; 44cd0189299f484dcbd51400b994daf585923e9e8dDavid Krauseimport android.util.Config; 45cd0189299f484dcbd51400b994daf585923e9e8dDavid Krauseimport android.util.Log; 46cd0189299f484dcbd51400b994daf585923e9e8dDavid Krauseimport android.widget.Toast; 47cd0189299f484dcbd51400b994daf585923e9e8dDavid Krause 48cd0189299f484dcbd51400b994daf585923e9e8dDavid Krausepublic class DownloadManager { 49cd0189299f484dcbd51400b994daf585923e9e8dDavid Krause private static final String TAG = "DownloadManager"; 50cd0189299f484dcbd51400b994daf585923e9e8dDavid Krause private static final boolean DEBUG = false; 51cd0189299f484dcbd51400b994daf585923e9e8dDavid Krause private static final boolean LOCAL_LOGV = DEBUG ? Config.LOGD : Config.LOGV; 52cd0189299f484dcbd51400b994daf585923e9e8dDavid Krause 53cd0189299f484dcbd51400b994daf585923e9e8dDavid Krause private static final int DEFERRED_MASK = 0x04; 54cd0189299f484dcbd51400b994daf585923e9e8dDavid Krause 55cd0189299f484dcbd51400b994daf585923e9e8dDavid Krause public static final int STATE_UNSTARTED = 0x80; 56cd0189299f484dcbd51400b994daf585923e9e8dDavid Krause public static final int STATE_DOWNLOADING = 0x81; 57cd0189299f484dcbd51400b994daf585923e9e8dDavid Krause public static final int STATE_TRANSIENT_FAILURE = 0x82; 58cd0189299f484dcbd51400b994daf585923e9e8dDavid Krause public static final int STATE_PERMANENT_FAILURE = 0x87; 59cd0189299f484dcbd51400b994daf585923e9e8dDavid Krause 60cd0189299f484dcbd51400b994daf585923e9e8dDavid Krause private final Context mContext; 61cd0189299f484dcbd51400b994daf585923e9e8dDavid Krause private final Handler mHandler; 62cd0189299f484dcbd51400b994daf585923e9e8dDavid Krause private final SharedPreferences mPreferences; 63cd0189299f484dcbd51400b994daf585923e9e8dDavid Krause private boolean mAutoDownload; 64cd0189299f484dcbd51400b994daf585923e9e8dDavid Krause 65cd0189299f484dcbd51400b994daf585923e9e8dDavid Krause private final OnSharedPreferenceChangeListener mPreferencesChangeListener = 664a0b3738f8a710d2ffc8c49b3ae7e44100c88839Tim Park new OnSharedPreferenceChangeListener() { 674a0b3738f8a710d2ffc8c49b3ae7e44100c88839Tim Park public void onSharedPreferenceChanged(SharedPreferences prefs, String key) { 684a0b3738f8a710d2ffc8c49b3ae7e44100c88839Tim Park if (MessagingPreferenceActivity.AUTO_RETRIEVAL.equals(key) 694a0b3738f8a710d2ffc8c49b3ae7e44100c88839Tim Park || MessagingPreferenceActivity.RETRIEVAL_DURING_ROAMING.equals(key)) { 704a0b3738f8a710d2ffc8c49b3ae7e44100c88839Tim Park if (LOCAL_LOGV) { 714a0b3738f8a710d2ffc8c49b3ae7e44100c88839Tim Park Log.v(TAG, "Preferences updated."); 724a0b3738f8a710d2ffc8c49b3ae7e44100c88839Tim Park } 734a0b3738f8a710d2ffc8c49b3ae7e44100c88839Tim Park 744a0b3738f8a710d2ffc8c49b3ae7e44100c88839Tim Park synchronized (sInstance) { 754a0b3738f8a710d2ffc8c49b3ae7e44100c88839Tim Park mAutoDownload = getAutoDownloadState(prefs); 764a0b3738f8a710d2ffc8c49b3ae7e44100c88839Tim Park if (LOCAL_LOGV) { 774a0b3738f8a710d2ffc8c49b3ae7e44100c88839Tim Park Log.v(TAG, "mAutoDownload ------> " + mAutoDownload); 784a0b3738f8a710d2ffc8c49b3ae7e44100c88839Tim Park } 794a0b3738f8a710d2ffc8c49b3ae7e44100c88839Tim Park } 804a0b3738f8a710d2ffc8c49b3ae7e44100c88839Tim Park } 814a0b3738f8a710d2ffc8c49b3ae7e44100c88839Tim Park } 824a0b3738f8a710d2ffc8c49b3ae7e44100c88839Tim Park }; 834a0b3738f8a710d2ffc8c49b3ae7e44100c88839Tim Park 844a0b3738f8a710d2ffc8c49b3ae7e44100c88839Tim Park private final BroadcastReceiver mRoamingStateListener = 854a0b3738f8a710d2ffc8c49b3ae7e44100c88839Tim Park new BroadcastReceiver() { 864a0b3738f8a710d2ffc8c49b3ae7e44100c88839Tim Park @Override 874a0b3738f8a710d2ffc8c49b3ae7e44100c88839Tim Park public void onReceive(Context context, Intent intent) { 884a0b3738f8a710d2ffc8c49b3ae7e44100c88839Tim Park if (TelephonyIntents.ACTION_SERVICE_STATE_CHANGED.equals(intent.getAction())) { 894a0b3738f8a710d2ffc8c49b3ae7e44100c88839Tim Park if (LOCAL_LOGV) { 904a0b3738f8a710d2ffc8c49b3ae7e44100c88839Tim Park Log.v(TAG, "Service state changed: " + intent.getExtras()); 914a0b3738f8a710d2ffc8c49b3ae7e44100c88839Tim Park } 924a0b3738f8a710d2ffc8c49b3ae7e44100c88839Tim Park 934a0b3738f8a710d2ffc8c49b3ae7e44100c88839Tim Park ServiceState state = ServiceState.newFromBundle(intent.getExtras()); 94cd0189299f484dcbd51400b994daf585923e9e8dDavid Krause boolean isRoaming = state.getRoaming(); 954a0b3738f8a710d2ffc8c49b3ae7e44100c88839Tim Park if (LOCAL_LOGV) { 964a0b3738f8a710d2ffc8c49b3ae7e44100c88839Tim Park Log.v(TAG, "roaming ------> " + isRoaming); 97cd0189299f484dcbd51400b994daf585923e9e8dDavid Krause } 98cd0189299f484dcbd51400b994daf585923e9e8dDavid Krause synchronized (sInstance) { 99cd0189299f484dcbd51400b994daf585923e9e8dDavid Krause mAutoDownload = getAutoDownloadState(mPreferences, isRoaming); 100cd0189299f484dcbd51400b994daf585923e9e8dDavid Krause if (LOCAL_LOGV) { 101cd0189299f484dcbd51400b994daf585923e9e8dDavid Krause Log.v(TAG, "mAutoDownload ------> " + mAutoDownload); 102cd0189299f484dcbd51400b994daf585923e9e8dDavid Krause } 103cd0189299f484dcbd51400b994daf585923e9e8dDavid Krause } 104cd0189299f484dcbd51400b994daf585923e9e8dDavid Krause } 105cd0189299f484dcbd51400b994daf585923e9e8dDavid Krause } 106cd0189299f484dcbd51400b994daf585923e9e8dDavid Krause }; 107cd0189299f484dcbd51400b994daf585923e9e8dDavid Krause 108cd0189299f484dcbd51400b994daf585923e9e8dDavid Krause private static DownloadManager sInstance; 109cd0189299f484dcbd51400b994daf585923e9e8dDavid Krause 110cd0189299f484dcbd51400b994daf585923e9e8dDavid Krause private DownloadManager(Context context) { 111cd0189299f484dcbd51400b994daf585923e9e8dDavid Krause mContext = context; 112cd0189299f484dcbd51400b994daf585923e9e8dDavid Krause mHandler = new Handler(); 113cd0189299f484dcbd51400b994daf585923e9e8dDavid Krause mPreferences = PreferenceManager.getDefaultSharedPreferences(context); 114cd0189299f484dcbd51400b994daf585923e9e8dDavid Krause mPreferences.registerOnSharedPreferenceChangeListener(mPreferencesChangeListener); 115cd0189299f484dcbd51400b994daf585923e9e8dDavid Krause 116cd0189299f484dcbd51400b994daf585923e9e8dDavid Krause context.registerReceiver( 117948a17dc246520345b81455fdae0e1d628adc263Li Zhe mRoamingStateListener, 118cd0189299f484dcbd51400b994daf585923e9e8dDavid Krause new IntentFilter(TelephonyIntents.ACTION_SERVICE_STATE_CHANGED)); 119cd0189299f484dcbd51400b994daf585923e9e8dDavid Krause 120cd0189299f484dcbd51400b994daf585923e9e8dDavid Krause mAutoDownload = getAutoDownloadState(mPreferences); 121cd0189299f484dcbd51400b994daf585923e9e8dDavid Krause if (LOCAL_LOGV) { 122cd0189299f484dcbd51400b994daf585923e9e8dDavid Krause Log.v(TAG, "mAutoDownload ------> " + mAutoDownload); 123cd0189299f484dcbd51400b994daf585923e9e8dDavid Krause } 124cd0189299f484dcbd51400b994daf585923e9e8dDavid Krause } 125cd0189299f484dcbd51400b994daf585923e9e8dDavid Krause 126cd0189299f484dcbd51400b994daf585923e9e8dDavid Krause public boolean isAuto() { 127cd0189299f484dcbd51400b994daf585923e9e8dDavid Krause return mAutoDownload; 128cd0189299f484dcbd51400b994daf585923e9e8dDavid Krause } 129cd0189299f484dcbd51400b994daf585923e9e8dDavid Krause 130cd0189299f484dcbd51400b994daf585923e9e8dDavid Krause public static void init(Context context) { 131cd0189299f484dcbd51400b994daf585923e9e8dDavid Krause if (LOCAL_LOGV) { 132cd0189299f484dcbd51400b994daf585923e9e8dDavid Krause Log.v(TAG, "DownloadManager.init()"); 133cd0189299f484dcbd51400b994daf585923e9e8dDavid Krause } 134cd0189299f484dcbd51400b994daf585923e9e8dDavid Krause 135cd0189299f484dcbd51400b994daf585923e9e8dDavid Krause if (sInstance != null) { 136cd0189299f484dcbd51400b994daf585923e9e8dDavid Krause Log.w(TAG, "Already initialized."); 137cd0189299f484dcbd51400b994daf585923e9e8dDavid Krause } 138cd0189299f484dcbd51400b994daf585923e9e8dDavid Krause sInstance = new DownloadManager(context); 139cd0189299f484dcbd51400b994daf585923e9e8dDavid Krause } 140cd0189299f484dcbd51400b994daf585923e9e8dDavid Krause 141cd0189299f484dcbd51400b994daf585923e9e8dDavid Krause public static DownloadManager getInstance() { 142cd0189299f484dcbd51400b994daf585923e9e8dDavid Krause if (sInstance == null) { 143cd0189299f484dcbd51400b994daf585923e9e8dDavid Krause throw new IllegalStateException("Uninitialized."); 144cd0189299f484dcbd51400b994daf585923e9e8dDavid Krause } 145cd0189299f484dcbd51400b994daf585923e9e8dDavid Krause return sInstance; 146cd0189299f484dcbd51400b994daf585923e9e8dDavid Krause } 147cd0189299f484dcbd51400b994daf585923e9e8dDavid Krause 148cd0189299f484dcbd51400b994daf585923e9e8dDavid Krause static boolean getAutoDownloadState(SharedPreferences prefs) { 149cd0189299f484dcbd51400b994daf585923e9e8dDavid Krause return getAutoDownloadState(prefs, isRoaming()); 150cd0189299f484dcbd51400b994daf585923e9e8dDavid Krause } 151cd0189299f484dcbd51400b994daf585923e9e8dDavid Krause 152cd0189299f484dcbd51400b994daf585923e9e8dDavid Krause static boolean getAutoDownloadState(SharedPreferences prefs, boolean roaming) { 153cd0189299f484dcbd51400b994daf585923e9e8dDavid Krause boolean autoDownload = prefs.getBoolean( 154cd0189299f484dcbd51400b994daf585923e9e8dDavid Krause MessagingPreferenceActivity.AUTO_RETRIEVAL, true); 155cd0189299f484dcbd51400b994daf585923e9e8dDavid Krause 156cd0189299f484dcbd51400b994daf585923e9e8dDavid Krause if (LOCAL_LOGV) { 157 Log.v(TAG, "auto download without roaming -> " + autoDownload); 158 } 159 160 if (autoDownload) { 161 boolean alwaysAuto = prefs.getBoolean( 162 MessagingPreferenceActivity.RETRIEVAL_DURING_ROAMING, false); 163 164 if (LOCAL_LOGV) { 165 Log.v(TAG, "auto download during roaming -> " + alwaysAuto); 166 } 167 168 if (!roaming || alwaysAuto) { 169 return true; 170 } 171 } 172 return false; 173 } 174 175 static boolean isRoaming() { 176 String roaming = SystemProperties.get( 177 TelephonyProperties.PROPERTY_OPERATOR_ISROAMING, null); 178 if (LOCAL_LOGV) { 179 Log.v(TAG, "roaming ------> " + roaming); 180 } 181 return "true".equals(roaming); 182 } 183 184 public void markState(final Uri uri, int state) { 185 // Notify user if downloading permanently failed. 186 if (state == STATE_PERMANENT_FAILURE) { 187 mHandler.post(new Runnable() { 188 public void run() { 189 try { 190 Toast.makeText(mContext, getMessage(uri), 191 Toast.LENGTH_LONG).show(); 192 } catch (MmsException e) { 193 Log.e(TAG, e.getMessage(), e); 194 } 195 } 196 }); 197 } else if (!mAutoDownload) { 198 state |= DEFERRED_MASK; 199 } 200 201 // Use the STATUS field to store the state of downloading process 202 // because it's useless for M-Notification.ind. 203 ContentValues values = new ContentValues(1); 204 values.put(Mms.STATUS, state); 205 SqliteWrapper.update(mContext, mContext.getContentResolver(), 206 uri, values, null, null); 207 } 208 209 private String getMessage(Uri uri) throws MmsException { 210 NotificationInd ind = (NotificationInd) PduPersister 211 .getPduPersister(mContext).load(uri); 212 213 EncodedStringValue v = ind.getSubject(); 214 String subject = (v != null) ? v.getString() 215 : mContext.getString(R.string.no_subject); 216 217 v = ind.getFrom(); 218 String from = (v != null) 219 ? ContactInfoCache.getInstance().getContactName(v.getString()) 220 : mContext.getString(R.string.unknown_sender); 221 222 return mContext.getString(R.string.dl_failure_notification, subject, from); 223 } 224 225 public int getState(Uri uri) { 226 Cursor cursor = SqliteWrapper.query(mContext, mContext.getContentResolver(), 227 uri, new String[] {Mms.STATUS}, null, null, null); 228 229 if (cursor != null) { 230 try { 231 if (cursor.moveToFirst()) { 232 return cursor.getInt(0) &~ DEFERRED_MASK; 233 } 234 } finally { 235 cursor.close(); 236 } 237 } 238 return STATE_UNSTARTED; 239 } 240} 241