• 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 com.android.mms.R;
21 import com.android.mms.data.Contact;
22 import com.android.mms.ui.MessagingPreferenceActivity;
23 import com.google.android.mms.MmsException;
24 import com.google.android.mms.pdu.EncodedStringValue;
25 import com.google.android.mms.pdu.NotificationInd;
26 import com.google.android.mms.pdu.PduPersister;
27 import android.database.sqlite.SqliteWrapper;
28 import com.android.internal.telephony.TelephonyIntents;
29 import com.android.internal.telephony.TelephonyProperties;
30 
31 import android.content.BroadcastReceiver;
32 import android.content.ContentValues;
33 import android.content.Context;
34 import android.content.Intent;
35 import android.content.IntentFilter;
36 import android.content.SharedPreferences;
37 import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
38 import android.database.Cursor;
39 import android.net.Uri;
40 import android.os.Handler;
41 import android.preference.PreferenceManager;
42 import android.provider.Telephony.Mms;
43 import android.telephony.ServiceState;
44 import android.util.Log;
45 import android.widget.Toast;
46 
47 import android.os.SystemProperties;
48 
49 public class DownloadManager {
50     private static final String TAG = "DownloadManager";
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 
62     private final Context mContext;
63     private final Handler mHandler;
64     private final SharedPreferences mPreferences;
65     private boolean mAutoDownload;
66 
67     private final OnSharedPreferenceChangeListener mPreferencesChangeListener =
68         new OnSharedPreferenceChangeListener() {
69         public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
70             if (MessagingPreferenceActivity.AUTO_RETRIEVAL.equals(key)
71                     || MessagingPreferenceActivity.RETRIEVAL_DURING_ROAMING.equals(key)) {
72                 if (LOCAL_LOGV) {
73                     Log.v(TAG, "Preferences updated.");
74                 }
75 
76                 synchronized (sInstance) {
77                     mAutoDownload = getAutoDownloadState(prefs);
78                     if (LOCAL_LOGV) {
79                         Log.v(TAG, "mAutoDownload ------> " + mAutoDownload);
80                     }
81                 }
82             }
83         }
84     };
85 
86     private final BroadcastReceiver mRoamingStateListener =
87         new BroadcastReceiver() {
88         @Override
89         public void onReceive(Context context, Intent intent) {
90             if (TelephonyIntents.ACTION_SERVICE_STATE_CHANGED.equals(intent.getAction())) {
91                 if (LOCAL_LOGV) {
92                     Log.v(TAG, "Service state changed: " + intent.getExtras());
93                 }
94 
95                 ServiceState state = ServiceState.newFromBundle(intent.getExtras());
96                 boolean isRoaming = state.getRoaming();
97                 if (LOCAL_LOGV) {
98                     Log.v(TAG, "roaming ------> " + isRoaming);
99                 }
100                 synchronized (sInstance) {
101                     mAutoDownload = getAutoDownloadState(mPreferences, isRoaming);
102                     if (LOCAL_LOGV) {
103                         Log.v(TAG, "mAutoDownload ------> " + mAutoDownload);
104                     }
105                 }
106             }
107         }
108     };
109 
110     private static DownloadManager sInstance;
111 
DownloadManager(Context context)112     private DownloadManager(Context context) {
113         mContext = context;
114         mHandler = new Handler();
115         mPreferences = PreferenceManager.getDefaultSharedPreferences(context);
116         mPreferences.registerOnSharedPreferenceChangeListener(mPreferencesChangeListener);
117 
118         context.registerReceiver(
119                 mRoamingStateListener,
120                 new IntentFilter(TelephonyIntents.ACTION_SERVICE_STATE_CHANGED));
121 
122         mAutoDownload = getAutoDownloadState(mPreferences);
123         if (LOCAL_LOGV) {
124             Log.v(TAG, "mAutoDownload ------> " + mAutoDownload);
125         }
126     }
127 
isAuto()128     public boolean isAuto() {
129         return mAutoDownload;
130     }
131 
init(Context context)132     public static void init(Context context) {
133         if (LOCAL_LOGV) {
134             Log.v(TAG, "DownloadManager.init()");
135         }
136 
137         if (sInstance != null) {
138             Log.w(TAG, "Already initialized.");
139         }
140         sInstance = new DownloadManager(context);
141     }
142 
getInstance()143     public static DownloadManager getInstance() {
144         if (sInstance == null) {
145             throw new IllegalStateException("Uninitialized.");
146         }
147         return sInstance;
148     }
149 
getAutoDownloadState(SharedPreferences prefs)150     static boolean getAutoDownloadState(SharedPreferences prefs) {
151         return getAutoDownloadState(prefs, isRoaming());
152     }
153 
getAutoDownloadState(SharedPreferences prefs, boolean roaming)154     static boolean getAutoDownloadState(SharedPreferences prefs, boolean roaming) {
155         boolean autoDownload = prefs.getBoolean(
156                 MessagingPreferenceActivity.AUTO_RETRIEVAL, true);
157 
158         if (LOCAL_LOGV) {
159             Log.v(TAG, "auto download without roaming -> " + autoDownload);
160         }
161 
162         if (autoDownload) {
163             boolean alwaysAuto = prefs.getBoolean(
164                     MessagingPreferenceActivity.RETRIEVAL_DURING_ROAMING, false);
165 
166             if (LOCAL_LOGV) {
167                 Log.v(TAG, "auto download during roaming -> " + alwaysAuto);
168             }
169 
170             if (!roaming || alwaysAuto) {
171                 return true;
172             }
173         }
174         return false;
175     }
176 
isRoaming()177     static boolean isRoaming() {
178         // TODO: fix and put in Telephony layer
179         String roaming = SystemProperties.get(
180                 TelephonyProperties.PROPERTY_OPERATOR_ISROAMING, null);
181         if (LOCAL_LOGV) {
182             Log.v(TAG, "roaming ------> " + roaming);
183         }
184         return "true".equals(roaming);
185     }
186 
markState(final Uri uri, int state)187     public void markState(final Uri uri, int state) {
188         // Notify user if the message has expired.
189         try {
190             NotificationInd nInd = (NotificationInd) PduPersister.getPduPersister(mContext)
191                     .load(uri);
192             if ((nInd.getExpiry() < System.currentTimeMillis()/1000L)
193                 && (state == STATE_DOWNLOADING)) {
194                 mHandler.post(new Runnable() {
195                     public void run() {
196                         Toast.makeText(mContext, R.string.service_message_not_found,
197                                 Toast.LENGTH_LONG).show();
198                     }
199                 });
200                 SqliteWrapper.delete(mContext, mContext.getContentResolver(), uri, null, null);
201                 return;
202             }
203         } catch(MmsException e) {
204             Log.e(TAG, e.getMessage(), e);
205             return;
206         }
207 
208         // Notify user if downloading permanently failed.
209         if (state == STATE_PERMANENT_FAILURE) {
210             mHandler.post(new Runnable() {
211                 public void run() {
212                     try {
213                         Toast.makeText(mContext, getMessage(uri),
214                                 Toast.LENGTH_LONG).show();
215                     } catch (MmsException e) {
216                         Log.e(TAG, e.getMessage(), e);
217                     }
218                 }
219             });
220         } else if (!mAutoDownload) {
221             state |= DEFERRED_MASK;
222         }
223 
224         // Use the STATUS field to store the state of downloading process
225         // because it's useless for M-Notification.ind.
226         ContentValues values = new ContentValues(1);
227         values.put(Mms.STATUS, state);
228         SqliteWrapper.update(mContext, mContext.getContentResolver(),
229                     uri, values, null, null);
230     }
231 
showErrorCodeToast(int errorStr)232     public void showErrorCodeToast(int errorStr) {
233         final int errStr = errorStr;
234         mHandler.post(new Runnable() {
235             public void run() {
236                 try {
237                     Toast.makeText(mContext, errStr, Toast.LENGTH_LONG).show();
238                 } catch (Exception e) {
239                     Log.e(TAG,"Caught an exception in showErrorCodeToast");
240                 }
241             }
242         });
243     }
244 
getMessage(Uri uri)245     private String getMessage(Uri uri) throws MmsException {
246         NotificationInd ind = (NotificationInd) PduPersister
247                 .getPduPersister(mContext).load(uri);
248 
249         EncodedStringValue v = ind.getSubject();
250         String subject = (v != null) ? v.getString()
251                 : mContext.getString(R.string.no_subject);
252 
253         v = ind.getFrom();
254         String from = (v != null)
255                 ? Contact.get(v.getString(), false).getName()
256                 : mContext.getString(R.string.unknown_sender);
257 
258         return mContext.getString(R.string.dl_failure_notification, subject, from);
259     }
260 
getState(Uri uri)261     public int getState(Uri uri) {
262         Cursor cursor = SqliteWrapper.query(mContext, mContext.getContentResolver(),
263                             uri, new String[] {Mms.STATUS}, null, null, null);
264 
265         if (cursor != null) {
266             try {
267                 if (cursor.moveToFirst()) {
268                     return cursor.getInt(0) & ~DEFERRED_MASK;
269                 }
270             } finally {
271                 cursor.close();
272             }
273         }
274         return STATE_UNSTARTED;
275     }
276 }
277