DownloadManager.java revision 66dde9460badebf8e740275cabde9cca256006eb
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
18package com.android.mms.util;
19
20import com.android.internal.telephony.TelephonyIntents;
21import com.android.internal.telephony.TelephonyProperties;
22import com.android.mms.R;
23import com.android.mms.ui.MessagingPreferenceActivity;
24import com.google.android.mms.MmsException;
25import com.google.android.mms.pdu.EncodedStringValue;
26import com.google.android.mms.pdu.NotificationInd;
27import com.google.android.mms.pdu.PduPersister;
28import com.google.android.mms.util.SqliteWrapper;
29
30import android.content.BroadcastReceiver;
31import android.content.ContentValues;
32import android.content.Context;
33import android.content.Intent;
34import android.content.IntentFilter;
35import android.content.SharedPreferences;
36import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
37import android.database.Cursor;
38import android.net.Uri;
39import android.os.Handler;
40import android.os.SystemProperties;
41import android.preference.PreferenceManager;
42import android.provider.Telephony.Mms;
43import android.telephony.ServiceState;
44import android.util.Config;
45import android.util.Log;
46import android.widget.Toast;
47
48public class DownloadManager {
49    private static final String TAG = "DownloadManager";
50    private static final boolean DEBUG = false;
51    private static final boolean LOCAL_LOGV = DEBUG ? Config.LOGD : Config.LOGV;
52
53    private static final int DEFERRED_MASK           = 0x04;
54
55    public static final int STATE_UNSTARTED         = 0x80;
56    public static final int STATE_DOWNLOADING       = 0x81;
57    public static final int STATE_TRANSIENT_FAILURE = 0x82;
58    public static final int STATE_PERMANENT_FAILURE = 0x87;
59
60    private final Context mContext;
61    private final Handler mHandler;
62    private final SharedPreferences mPreferences;
63    private boolean mAutoDownload;
64
65    private final OnSharedPreferenceChangeListener mPreferencesChangeListener =
66        new OnSharedPreferenceChangeListener() {
67        public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
68            if (MessagingPreferenceActivity.AUTO_RETRIEVAL.equals(key)
69                    || MessagingPreferenceActivity.RETRIEVAL_DURING_ROAMING.equals(key)) {
70                if (LOCAL_LOGV) {
71                    Log.v(TAG, "Preferences updated.");
72                }
73
74                synchronized (sInstance) {
75                    mAutoDownload = getAutoDownloadState(prefs);
76                    if (LOCAL_LOGV) {
77                        Log.v(TAG, "mAutoDownload ------> " + mAutoDownload);
78                    }
79                }
80            }
81        }
82    };
83
84    private final BroadcastReceiver mRoamingStateListener =
85        new BroadcastReceiver() {
86        @Override
87        public void onReceive(Context context, Intent intent) {
88            if (TelephonyIntents.ACTION_SERVICE_STATE_CHANGED.equals(intent.getAction())) {
89                if (LOCAL_LOGV) {
90                    Log.v(TAG, "Service state changed: " + intent.getExtras());
91                }
92
93                ServiceState state = ServiceState.newFromBundle(intent.getExtras());
94                boolean isRoaming = state.getRoaming();
95                if (LOCAL_LOGV) {
96                    Log.v(TAG, "roaming ------> " + isRoaming);
97                }
98                synchronized (sInstance) {
99                    mAutoDownload = getAutoDownloadState(mPreferences, isRoaming);
100                    if (LOCAL_LOGV) {
101                        Log.v(TAG, "mAutoDownload ------> " + mAutoDownload);
102                    }
103                }
104            }
105        }
106    };
107
108    private static DownloadManager sInstance;
109
110    private DownloadManager(Context context) {
111        mContext = context;
112        mHandler = new Handler();
113        mPreferences = PreferenceManager.getDefaultSharedPreferences(context);
114        mPreferences.registerOnSharedPreferenceChangeListener(mPreferencesChangeListener);
115
116        context.registerReceiver(
117                mRoamingStateListener,
118                new IntentFilter(TelephonyIntents.ACTION_SERVICE_STATE_CHANGED));
119
120        mAutoDownload = getAutoDownloadState(mPreferences);
121        if (LOCAL_LOGV) {
122            Log.v(TAG, "mAutoDownload ------> " + mAutoDownload);
123        }
124    }
125
126    public boolean isAuto() {
127        return mAutoDownload;
128    }
129
130    public static void init(Context context) {
131        if (LOCAL_LOGV) {
132            Log.v(TAG, "DownloadManager.init()");
133        }
134
135        if (sInstance != null) {
136            Log.w(TAG, "Already initialized.");
137        }
138        sInstance = new DownloadManager(context);
139    }
140
141    public static DownloadManager getInstance() {
142        if (sInstance == null) {
143            throw new IllegalStateException("Uninitialized.");
144        }
145        return sInstance;
146    }
147
148    static boolean getAutoDownloadState(SharedPreferences prefs) {
149        return getAutoDownloadState(prefs, isRoaming());
150    }
151
152    static boolean getAutoDownloadState(SharedPreferences prefs, boolean roaming) {
153        boolean autoDownload = prefs.getBoolean(
154                MessagingPreferenceActivity.AUTO_RETRIEVAL, true);
155
156        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