• 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.ui;
19 
20 import com.android.mms.R;
21 import com.google.android.mms.pdu.PduHeaders;
22 import android.database.sqlite.SqliteWrapper;
23 
24 import android.app.ListActivity;
25 import android.content.Intent;
26 import android.database.Cursor;
27 import android.net.Uri;
28 import android.os.Bundle;
29 import android.provider.Telephony.Mms;
30 import android.provider.Telephony.Sms;
31 import android.telephony.PhoneNumberUtils;
32 import android.text.TextUtils;
33 import android.util.Log;
34 import android.view.LayoutInflater;
35 import android.view.View;
36 import android.view.Window;
37 import android.widget.ListView;
38 
39 import java.util.ArrayList;
40 import java.util.HashMap;
41 import java.util.Iterator;
42 import java.util.List;
43 import java.util.Map;
44 import java.util.Set;
45 
46 /**
47  * This is the UI for displaying a delivery report:
48  *
49  * This activity can handle the following parameters from the intent
50  * by which it is launched:
51  *
52  * thread_id long The id of the conversation from which to get the recipients
53  *      for the report.
54  * message_id long The id of the message about which a report should be displayed.
55  * message_type String The type of message (Sms or Mms).  This is used in
56  *      conjunction with the message id to retrive the particular message that
57  *      the report will be about.
58  */
59 public class DeliveryReportActivity extends ListActivity {
60     private static final String LOG_TAG = "DeliveryReportActivity";
61 
62     static final String[] MMS_REPORT_REQUEST_PROJECTION = new String[] {
63         Mms.Addr.ADDRESS,       //0
64         Mms.DELIVERY_REPORT,    //1
65         Mms.READ_REPORT         //2
66     };
67 
68     static final String[] MMS_REPORT_STATUS_PROJECTION = new String[] {
69         Mms.Addr.ADDRESS,       //0
70         "delivery_status",      //1
71         "read_status"           //2
72     };
73 
74     static final String[] SMS_REPORT_STATUS_PROJECTION = new String[] {
75         Sms.ADDRESS,            //0
76         Sms.STATUS              //1
77     };
78 
79     // These indices must sync up with the projections above.
80     static final int COLUMN_RECIPIENT           = 0;
81     static final int COLUMN_DELIVERY_REPORT     = 1;
82     static final int COLUMN_READ_REPORT         = 2;
83     static final int COLUMN_DELIVERY_STATUS     = 1;
84     static final int COLUMN_READ_STATUS         = 2;
85 
86     private long mMessageId;
87     private String mMessageType;
88 
89     @Override
onCreate(Bundle icicle)90     protected void onCreate(Bundle icicle) {
91         super.onCreate(icicle);
92         requestWindowFeature(Window.FEATURE_NO_TITLE);
93         setContentView(R.layout.delivery_report_activity);
94 
95         Intent intent = getIntent();
96         mMessageId = getMessageId(icicle, intent);
97         mMessageType = getMessageType(icicle, intent);
98 
99         initListView();
100         initListAdapter();
101     }
102 
initListView()103     private void initListView() {
104         // Add the header for the list view.
105         LayoutInflater inflater = getLayoutInflater();
106         View header = inflater.inflate(R.layout.delivery_report_header, null);
107         getListView().addHeaderView(header, null, true);
108     }
109 
initListAdapter()110     private void initListAdapter() {
111         List<DeliveryReportItem> items = getReportItems();
112         if (items == null) {
113             items = new ArrayList<DeliveryReportItem>(1);
114             items.add(new DeliveryReportItem("", getString(R.string.status_none)));
115             Log.w(LOG_TAG, "cursor == null");
116         }
117         setListAdapter(new DeliveryReportAdapter(this, items));
118     }
119 
120     @Override
onResume()121     public void onResume() {
122         super.onResume();
123         refreshDeliveryReport();
124     }
125 
refreshDeliveryReport()126     private void refreshDeliveryReport() {
127         ListView list = getListView();
128         list.invalidateViews();
129         list.requestFocus();
130     }
131 
getMessageId(Bundle icicle, Intent intent)132     private long getMessageId(Bundle icicle, Intent intent) {
133         long msgId = 0L;
134 
135         if (icicle != null) {
136             msgId = icicle.getLong("message_id");
137         }
138 
139         if (msgId == 0L) {
140             msgId = intent.getLongExtra("message_id", 0L);
141         }
142 
143         return msgId;
144     }
145 
getMessageType(Bundle icicle, Intent intent)146     private String getMessageType(Bundle icicle, Intent intent) {
147         String msgType = null;
148 
149         if (icicle != null) {
150             msgType = icicle.getString("message_type");
151         }
152 
153         if (msgType == null) {
154             msgType = intent.getStringExtra("message_type");
155         }
156 
157         return msgType;
158     }
159 
getReportItems()160     private List<DeliveryReportItem> getReportItems() {
161         if (mMessageType.equals("sms")) {
162             return getSmsReportItems();
163         } else {
164             return getMmsReportItems();
165         }
166     }
167 
getSmsReportItems()168     private List<DeliveryReportItem> getSmsReportItems() {
169         String selection = "_id = " + mMessageId;
170         Cursor c = SqliteWrapper.query(this, getContentResolver(), Sms.CONTENT_URI,
171                               SMS_REPORT_STATUS_PROJECTION, selection, null, null);
172         if (c == null) {
173             return null;
174         }
175 
176         try {
177             if (c.getCount() <= 0) {
178                 return null;
179             }
180 
181             List<DeliveryReportItem> items = new ArrayList<DeliveryReportItem>();
182             while (c.moveToNext()) {
183                 items.add(new DeliveryReportItem(
184                                 getString(R.string.recipient_label) + c.getString(COLUMN_RECIPIENT),
185                                 getString(R.string.status_label) +
186                                     getSmsStatusText(c.getInt(COLUMN_DELIVERY_STATUS))));
187             }
188             return items;
189         } finally {
190             c.close();
191         }
192     }
193 
getMmsReportStatusText( MmsReportRequest request, Map<String, MmsReportStatus> reportStatus)194     private String getMmsReportStatusText(
195             MmsReportRequest request,
196             Map<String, MmsReportStatus> reportStatus) {
197         if (reportStatus == null) {
198             // haven't received any reports.
199             return getString(R.string.status_pending);
200         }
201 
202         String recipient = request.getRecipient();
203         recipient = (Mms.isEmailAddress(recipient))?
204                 Mms.extractAddrSpec(recipient): PhoneNumberUtils.stripSeparators(recipient);
205         MmsReportStatus status = queryStatusByRecipient(reportStatus, recipient);
206         if (status == null) {
207             // haven't received any reports.
208             return getString(R.string.status_pending);
209         }
210 
211         if (request.isReadReportRequested()) {
212             if (status.readStatus != 0) {
213                 switch (status.readStatus) {
214                     case PduHeaders.READ_STATUS_READ:
215                         return getString(R.string.status_read);
216                     case PduHeaders.READ_STATUS__DELETED_WITHOUT_BEING_READ:
217                         return getString(R.string.status_unread);
218                 }
219             }
220         }
221 
222         switch (status.deliveryStatus) {
223             case 0: // No delivery report received so far.
224                 return getString(R.string.status_pending);
225             case PduHeaders.STATUS_FORWARDED:
226             case PduHeaders.STATUS_RETRIEVED:
227                 return getString(R.string.status_received);
228             case PduHeaders.STATUS_REJECTED:
229                 return getString(R.string.status_rejected);
230             default:
231                 return getString(R.string.status_failed);
232         }
233     }
234 
queryStatusByRecipient( Map<String, MmsReportStatus> status, String recipient)235     private static MmsReportStatus queryStatusByRecipient(
236             Map<String, MmsReportStatus> status, String recipient) {
237         Set<String> recipientSet = status.keySet();
238         Iterator<String> iterator = recipientSet.iterator();
239         while (iterator.hasNext()) {
240             String r = iterator.next();
241             if (Mms.isEmailAddress(recipient)) {
242                 if (TextUtils.equals(r, recipient)) {
243                     return status.get(r);
244                 }
245             }
246             else if (PhoneNumberUtils.compare(r, recipient)) {
247                 return status.get(r);
248             }
249         }
250         return null;
251     }
252 
getMmsReportItems()253     private List<DeliveryReportItem> getMmsReportItems() {
254         List<MmsReportRequest> reportReqs = getMmsReportRequests();
255         if (null == reportReqs) {
256             return null;
257         }
258 
259         if (reportReqs.size() == 0) {
260             return null;
261         }
262 
263         Map<String, MmsReportStatus> reportStatus = getMmsReportStatus();
264         List<DeliveryReportItem> items = new ArrayList<DeliveryReportItem>();
265         for (MmsReportRequest reportReq : reportReqs) {
266             String statusText = getString(R.string.status_label) +
267                 getMmsReportStatusText(reportReq, reportStatus);
268             items.add(new DeliveryReportItem(getString(R.string.recipient_label) +
269                     reportReq.getRecipient(), statusText));
270         }
271         return items;
272     }
273 
getMmsReportStatus()274     private Map<String, MmsReportStatus> getMmsReportStatus() {
275         Uri uri = Uri.withAppendedPath(Mms.REPORT_STATUS_URI,
276                                        String.valueOf(mMessageId));
277         Cursor c = SqliteWrapper.query(this, getContentResolver(), uri,
278                        MMS_REPORT_STATUS_PROJECTION, null, null, null);
279 
280         if (c == null) {
281             return null;
282         }
283 
284         try {
285             Map<String, MmsReportStatus> statusMap =
286                     new HashMap<String, MmsReportStatus>();
287 
288             while (c.moveToNext()) {
289                 String recipient = c.getString(COLUMN_RECIPIENT);
290                 recipient = (Mms.isEmailAddress(recipient))?
291                                         Mms.extractAddrSpec(recipient):
292                                             PhoneNumberUtils.stripSeparators(recipient);
293                 MmsReportStatus status = new MmsReportStatus(
294                                         c.getInt(COLUMN_DELIVERY_STATUS),
295                                         c.getInt(COLUMN_READ_STATUS));
296                 statusMap.put(recipient, status);
297             }
298             return statusMap;
299         } finally {
300             c.close();
301         }
302     }
303 
getMmsReportRequests()304     private List<MmsReportRequest> getMmsReportRequests() {
305         Uri uri = Uri.withAppendedPath(Mms.REPORT_REQUEST_URI,
306                                        String.valueOf(mMessageId));
307         Cursor c = SqliteWrapper.query(this, getContentResolver(), uri,
308                       MMS_REPORT_REQUEST_PROJECTION, null, null, null);
309 
310         if (c == null) {
311             return null;
312         }
313 
314         try {
315             if (c.getCount() <= 0) {
316                 return null;
317             }
318 
319             List<MmsReportRequest> reqList = new ArrayList<MmsReportRequest>();
320             while (c.moveToNext()) {
321                 reqList.add(new MmsReportRequest(
322                                 c.getString(COLUMN_RECIPIENT),
323                                 c.getInt(COLUMN_DELIVERY_REPORT),
324                                 c.getInt(COLUMN_READ_REPORT)));
325             }
326             return reqList;
327         } finally {
328             c.close();
329         }
330     }
331 
getSmsStatusText(int status)332     private String getSmsStatusText(int status) {
333         if (status == Sms.STATUS_NONE) {
334             // No delivery report requested
335             return getString(R.string.status_none);
336         } else if (status >= Sms.STATUS_FAILED) {
337             // Failure
338             return getString(R.string.status_failed);
339         } else if (status >= Sms.STATUS_PENDING) {
340             // Pending
341             return getString(R.string.status_pending);
342         } else {
343             // Success
344             return getString(R.string.status_received);
345         }
346     }
347 
348     private static final class MmsReportStatus {
349         final int deliveryStatus;
350         final int readStatus;
351 
MmsReportStatus(int drStatus, int rrStatus)352         public MmsReportStatus(int drStatus, int rrStatus) {
353             deliveryStatus = drStatus;
354             readStatus = rrStatus;
355         }
356     }
357 
358     private static final class MmsReportRequest {
359         private final String mRecipient;
360         private final boolean mIsDeliveryReportRequsted;
361         private final boolean mIsReadReportRequested;
362 
MmsReportRequest(String recipient, int drValue, int rrValue)363         public MmsReportRequest(String recipient, int drValue, int rrValue) {
364             mRecipient = recipient;
365             mIsDeliveryReportRequsted = drValue == PduHeaders.VALUE_YES;
366             mIsReadReportRequested = rrValue == PduHeaders.VALUE_YES;
367         }
368 
getRecipient()369         public String getRecipient() {
370             return mRecipient;
371         }
372 
isDeliveryReportRequested()373         public boolean isDeliveryReportRequested() {
374             return mIsDeliveryReportRequsted;
375         }
376 
isReadReportRequested()377         public boolean isReadReportRequested() {
378             return mIsReadReportRequested;
379         }
380     }
381 }
382