• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2008 Esmertec AG.
3  * Copyright (C) 2008 The Android Open Source Project
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 package com.android.mms.util;
19 
20 import android.content.BroadcastReceiver;
21 import android.content.ContentValues;
22 import android.content.Context;
23 import android.content.Intent;
24 import android.content.IntentFilter;
25 import android.content.SharedPreferences;
26 import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
27 import android.database.Cursor;
28 import android.database.sqlite.SqliteWrapper;
29 import android.net.Uri;
30 import android.os.Handler;
31 import android.os.SystemProperties;
32 import android.preference.PreferenceManager;
33 import android.provider.Telephony.Mms;
34 import android.telephony.ServiceState;
35 import android.util.Log;
36 import android.widget.Toast;
37 
38 import com.android.internal.telephony.TelephonyIntents;
39 import com.android.internal.telephony.TelephonyProperties;
40 import com.android.mms.LogTag;
41 import com.android.mms.R;
42 import com.android.mms.data.Contact;
43 import com.android.mms.ui.MessagingPreferenceActivity;
44 import com.google.android.mms.MmsException;
45 import com.google.android.mms.pdu.EncodedStringValue;
46 import com.google.android.mms.pdu.NotificationInd;
47 import com.google.android.mms.pdu.PduPersister;
48 
49 public class DownloadManager {
50     private static final String TAG = LogTag.TAG;
51     private static final boolean DEBUG = false;
52     private static final boolean LOCAL_LOGV = false;
53 
54     public static final int DEFERRED_MASK           = 0x04;
55 
56     public static final int STATE_UNKNOWN           = 0x00;
57     public static final int STATE_UNSTARTED         = 0x80;
58     public static final int STATE_DOWNLOADING       = 0x81;
59     public static final int STATE_TRANSIENT_FAILURE = 0x82;
60     public static final int STATE_PERMANENT_FAILURE = 0x87;
61     public static final int STATE_PRE_DOWNLOADING   = 0x88;
62     // TransactionService will skip downloading Mms if auto-download is off
63     public static final int STATE_SKIP_RETRYING     = 0x89;
64 
65     private final Context mContext;
66     private final Handler mHandler;
67     private final SharedPreferences mPreferences;
68     private boolean mAutoDownload;
69 
70     private final OnSharedPreferenceChangeListener mPreferencesChangeListener =
71         new OnSharedPreferenceChangeListener() {
72         public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
73             if (MessagingPreferenceActivity.AUTO_RETRIEVAL.equals(key)
74                     || MessagingPreferenceActivity.RETRIEVAL_DURING_ROAMING.equals(key)) {
75                 if (LOCAL_LOGV) {
76                     Log.v(TAG, "Preferences updated.");
77                 }
78 
79                 synchronized (sInstance) {
80                     mAutoDownload = getAutoDownloadState(prefs);
81                     if (LOCAL_LOGV) {
82                         Log.v(TAG, "mAutoDownload ------> " + mAutoDownload);
83                     }
84                 }
85             }
86         }
87     };
88 
89     private final BroadcastReceiver mRoamingStateListener =
90         new BroadcastReceiver() {
91         @Override
92         public void onReceive(Context context, Intent intent) {
93             if (TelephonyIntents.ACTION_SERVICE_STATE_CHANGED.equals(intent.getAction())) {
94                 if (LOCAL_LOGV) {
95                     Log.v(TAG, "Service state changed: " + intent.getExtras());
96                 }
97 
98                 ServiceState state = ServiceState.newFromBundle(intent.getExtras());
99                 boolean isRoaming = state.getRoaming();
100                 if (LOCAL_LOGV) {
101                     Log.v(TAG, "roaming ------> " + isRoaming);
102                 }
103                 synchronized (sInstance) {
104                     mAutoDownload = getAutoDownloadState(mPreferences, isRoaming);
105                     if (LOCAL_LOGV) {
106                         Log.v(TAG, "mAutoDownload ------> " + mAutoDownload);
107                     }
108                 }
109             }
110         }
111     };
112 
113     private static DownloadManager sInstance;
114 
DownloadManager(Context context)115     private DownloadManager(Context context) {
116         mContext = context;
117         mHandler = new Handler();
118         mPreferences = PreferenceManager.getDefaultSharedPreferences(context);
119         mPreferences.registerOnSharedPreferenceChangeListener(mPreferencesChangeListener);
120 
121         context.registerReceiver(
122                 mRoamingStateListener,
123                 new IntentFilter(TelephonyIntents.ACTION_SERVICE_STATE_CHANGED));
124 
125         mAutoDownload = getAutoDownloadState(mPreferences);
126         if (LOCAL_LOGV) {
127             Log.v(TAG, "mAutoDownload ------> " + mAutoDownload);
128         }
129     }
130 
isAuto()131     public boolean isAuto() {
132         return mAutoDownload;
133     }
134 
init(Context context)135     public static void init(Context context) {
136         if (LOCAL_LOGV) {
137             Log.v(TAG, "DownloadManager.init()");
138         }
139 
140         if (sInstance != null) {
141             Log.w(TAG, "Already initialized.");
142         }
143         sInstance = new DownloadManager(context);
144     }
145 
getInstance()146     public static DownloadManager getInstance() {
147         if (sInstance == null) {
148             throw new IllegalStateException("Uninitialized.");
149         }
150         return sInstance;
151     }
152 
getAutoDownloadState(SharedPreferences prefs)153     static boolean getAutoDownloadState(SharedPreferences prefs) {
154         return getAutoDownloadState(prefs, isRoaming());
155     }
156 
getAutoDownloadState(SharedPreferences prefs, boolean roaming)157     static boolean getAutoDownloadState(SharedPreferences prefs, boolean roaming) {
158         boolean autoDownload = prefs.getBoolean(
159                 MessagingPreferenceActivity.AUTO_RETRIEVAL, true);
160 
161         if (LOCAL_LOGV) {
162             Log.v(TAG, "auto download without roaming -> " + autoDownload);
163         }
164 
165         if (autoDownload) {
166             boolean alwaysAuto = prefs.getBoolean(
167                     MessagingPreferenceActivity.RETRIEVAL_DURING_ROAMING, false);
168 
169             if (LOCAL_LOGV) {
170                 Log.v(TAG, "auto download during roaming -> " + alwaysAuto);
171             }
172 
173             if (!roaming || alwaysAuto) {
174                 return true;
175             }
176         }
177         return false;
178     }
179 
isRoaming()180     static boolean isRoaming() {
181         // TODO: fix and put in Telephony layer
182         String roaming = SystemProperties.get(
183                 TelephonyProperties.PROPERTY_OPERATOR_ISROAMING, null);
184         if (LOCAL_LOGV) {
185             Log.v(TAG, "roaming ------> " + roaming);
186         }
187         return "true".equals(roaming);
188     }
189 
markState(final Uri uri, int state)190     public void markState(final Uri uri, int state) {
191         // Notify user if the message has expired.
192         try {
193             NotificationInd nInd = (NotificationInd) PduPersister.getPduPersister(mContext)
194                     .load(uri);
195             if ((nInd.getExpiry() < System.currentTimeMillis() / 1000L)
196                     && (state == STATE_DOWNLOADING || state == STATE_PRE_DOWNLOADING)) {
197                 mHandler.post(new Runnable() {
198                     public void run() {
199                         Toast.makeText(mContext, R.string.service_message_not_found,
200                                 Toast.LENGTH_LONG).show();
201                     }
202                 });
203                 SqliteWrapper.delete(mContext, mContext.getContentResolver(), uri, null, null);
204                 return;
205             }
206         } catch(MmsException e) {
207             Log.e(TAG, e.getMessage(), e);
208             return;
209         }
210 
211         // Notify user if downloading permanently failed.
212         if (state == STATE_PERMANENT_FAILURE) {
213             mHandler.post(new Runnable() {
214                 public void run() {
215                     try {
216                         Toast.makeText(mContext, getMessage(uri),
217                                 Toast.LENGTH_LONG).show();
218                     } catch (MmsException e) {
219                         Log.e(TAG, e.getMessage(), e);
220                     }
221                 }
222             });
223         } else if (!mAutoDownload) {
224             state |= DEFERRED_MASK;
225         }
226 
227         // Use the STATUS field to store the state of downloading process
228         // because it's useless for M-Notification.ind.
229         ContentValues values = new ContentValues(1);
230         values.put(Mms.STATUS, state);
231         SqliteWrapper.update(mContext, mContext.getContentResolver(),
232                     uri, values, null, null);
233     }
234 
showErrorCodeToast(int errorStr)235     public void showErrorCodeToast(int errorStr) {
236         final int errStr = errorStr;
237         mHandler.post(new Runnable() {
238             public void run() {
239                 try {
240                     Toast.makeText(mContext, errStr, Toast.LENGTH_LONG).show();
241                 } catch (Exception e) {
242                     Log.e(TAG,"Caught an exception in showErrorCodeToast");
243                 }
244             }
245         });
246     }
247 
getMessage(Uri uri)248     private String getMessage(Uri uri) throws MmsException {
249         NotificationInd ind = (NotificationInd) PduPersister
250                 .getPduPersister(mContext).load(uri);
251 
252         EncodedStringValue v = ind.getSubject();
253         String subject = (v != null) ? v.getString()
254                 : mContext.getString(R.string.no_subject);
255 
256         v = ind.getFrom();
257         String from = (v != null)
258                 ? Contact.get(v.getString(), false).getName()
259                 : mContext.getString(R.string.unknown_sender);
260 
261         return mContext.getString(R.string.dl_failure_notification, subject, from);
262     }
263 
getState(Uri uri)264     public int getState(Uri uri) {
265         Cursor cursor = SqliteWrapper.query(mContext, mContext.getContentResolver(),
266                             uri, new String[] {Mms.STATUS}, null, null, null);
267 
268         if (cursor != null) {
269             try {
270                 if (cursor.moveToFirst()) {
271                     return cursor.getInt(0) & ~DEFERRED_MASK;
272                 }
273             } finally {
274                 cursor.close();
275             }
276         }
277         return STATE_UNSTARTED;
278     }
279 }
280