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