1/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.messaging.datamodel.action;
18
19import android.content.ContentUris;
20import android.content.ContentValues;
21import android.net.Uri;
22import android.os.Parcel;
23import android.os.Parcelable;
24import android.provider.Telephony;
25
26import com.android.messaging.datamodel.BugleDatabaseOperations;
27import com.android.messaging.datamodel.DataModel;
28import com.android.messaging.datamodel.DatabaseHelper;
29import com.android.messaging.datamodel.DatabaseWrapper;
30import com.android.messaging.datamodel.MessagingContentProvider;
31import com.android.messaging.datamodel.data.MessageData;
32import com.android.messaging.sms.MmsUtils;
33import com.android.messaging.util.Assert;
34import com.android.messaging.util.LogUtil;
35
36import java.util.concurrent.TimeUnit;
37
38public class ProcessDeliveryReportAction extends Action implements Parcelable {
39    private static final String TAG = LogUtil.BUGLE_DATAMODEL_TAG;
40
41    private static final String KEY_URI = "uri";
42    private static final String KEY_STATUS = "status";
43
44    private ProcessDeliveryReportAction(final Uri uri, final int status) {
45        actionParameters.putParcelable(KEY_URI, uri);
46        actionParameters.putInt(KEY_STATUS, status);
47    }
48
49    public static void deliveryReportReceived(final Uri uri, final int status) {
50        final ProcessDeliveryReportAction action = new ProcessDeliveryReportAction(uri, status);
51        action.start();
52    }
53
54    @Override
55    protected Object executeAction() {
56        final Uri smsMessageUri = actionParameters.getParcelable(KEY_URI);
57        final int status = actionParameters.getInt(KEY_STATUS);
58
59        final DatabaseWrapper db = DataModel.get().getDatabase();
60
61        final long messageRowId = ContentUris.parseId(smsMessageUri);
62        if (messageRowId < 0) {
63            LogUtil.e(TAG, "ProcessDeliveryReportAction: can't find message");
64            return null;
65        }
66        final long timeSentInMillis = System.currentTimeMillis();
67        // Update telephony provider
68        if (smsMessageUri != null) {
69            MmsUtils.updateSmsStatusAndDateSent(smsMessageUri, status, timeSentInMillis);
70        }
71
72        // Update local message
73        db.beginTransaction();
74        try {
75            final ContentValues values = new ContentValues();
76            final int bugleStatus = SyncMessageBatch.bugleStatusForSms(true /*outgoing*/,
77                    Telephony.Sms.MESSAGE_TYPE_SENT /* type */, status);
78            values.put(DatabaseHelper.MessageColumns.STATUS, bugleStatus);
79            values.put(DatabaseHelper.MessageColumns.SENT_TIMESTAMP,
80                    TimeUnit.MILLISECONDS.toMicros(timeSentInMillis));
81
82            final MessageData messageData =
83                    BugleDatabaseOperations.readMessageData(db, smsMessageUri);
84
85            // Check the message was not removed before the delivery report comes in
86            if (messageData !=  null) {
87                Assert.isTrue(smsMessageUri.equals(messageData.getSmsMessageUri()));
88
89                // Row must exist as was just loaded above (on ActionService thread)
90                BugleDatabaseOperations.updateMessageRow(db, messageData.getMessageId(), values);
91
92                MessagingContentProvider.notifyMessagesChanged(messageData.getConversationId());
93            }
94            db.setTransactionSuccessful();
95        } finally {
96            db.endTransaction();
97        }
98        return null;
99    }
100
101    private ProcessDeliveryReportAction(final Parcel in) {
102        super(in);
103    }
104
105    public static final Parcelable.Creator<ProcessDeliveryReportAction> CREATOR
106            = new Parcelable.Creator<ProcessDeliveryReportAction>() {
107        @Override
108        public ProcessDeliveryReportAction createFromParcel(final Parcel in) {
109            return new ProcessDeliveryReportAction(in);
110        }
111
112        @Override
113        public ProcessDeliveryReportAction[] newArray(final int size) {
114            return new ProcessDeliveryReportAction[size];
115        }
116    };
117
118    @Override
119    public void writeToParcel(final Parcel parcel, final int flags) {
120        writeActionToParcel(parcel, flags);
121    }
122}
123