/* * Copyright 2014 Jacob Klinker * * 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.ContentValues; import android.content.Context; import android.content.SharedPreferences; import android.database.Cursor; import android.database.sqlite.SqliteWrapper; import android.net.Uri; import android.os.Handler; import android.os.Looper; import android.preference.PreferenceManager; import android.provider.Telephony.Mms; import com.klinker.android.logger.Log; import android.widget.Toast; import com.android.internal.telephony.TelephonyProperties; import com.android.mms.LogTag; import com.android.mms.service_alt.SystemPropertiesProxy; import com.google.android.mms.MmsException; import com.google.android.mms.pdu_alt.EncodedStringValue; import com.google.android.mms.pdu_alt.NotificationInd; import com.google.android.mms.pdu_alt.PduPersister; import com.klinker.android.send_message.R; 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 static DownloadManager sInstance; private DownloadManager(Context context) { mContext = context; mHandler = new Handler(Looper.getMainLooper()); mPreferences = PreferenceManager.getDefaultSharedPreferences(context); mAutoDownload = getAutoDownloadState(context, 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(Context context, SharedPreferences prefs) { return getAutoDownloadState(prefs, isRoaming(context)); } static boolean getAutoDownloadState(SharedPreferences prefs, boolean roaming) { boolean autoDownload = prefs.getBoolean("auto_download_mms", true); if (LOCAL_LOGV) { Log.v(TAG, "auto download without roaming -> " + autoDownload); } if (autoDownload) { boolean alwaysAuto = true; if (LOCAL_LOGV) { Log.v(TAG, "auto download during roaming -> " + alwaysAuto); } if (!roaming || alwaysAuto) { return true; } } return false; } static boolean isRoaming(Context context) { // TODO: fix and put in Telephony layer String roaming = SystemPropertiesProxy.get(context, TelephonyProperties.PROPERTY_OPERATOR_ISROAMING, null); if (LOCAL_LOGV) { Log.v(TAG, "roaming ------> " + roaming); } return "true".equals(roaming); } 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); String from = 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()) { int state = cursor.getInt(0) & ~DEFERRED_MASK; cursor.close(); return state; } } finally { cursor.close(); } } return STATE_UNSTARTED; } }