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 
17 package com.android.messaging.ui;
18 
19 import android.app.Activity;
20 import android.app.AlertDialog;
21 import android.content.ContentValues;
22 import android.content.DialogInterface;
23 import android.content.DialogInterface.OnClickListener;
24 import android.content.Intent;
25 import android.os.Bundle;
26 import android.os.Handler;
27 import android.os.Message;
28 import android.os.SystemClock;
29 import android.provider.Telephony.Sms;
30 import android.text.TextUtils;
31 import android.util.Log;
32 import android.view.Window;
33 
34 import com.android.messaging.R;
35 import com.android.messaging.datamodel.action.ReceiveSmsMessageAction;
36 import com.android.messaging.util.Assert;
37 
38 import java.util.ArrayList;
39 
40 /**
41  * Display a class-zero SMS message to the user. Wait for the user to dismiss
42  * it.
43  */
44 public class ClassZeroActivity extends Activity {
45     private static final boolean VERBOSE = false;
46     private static final String TAG = "display_00";
47     private static final int ON_AUTO_SAVE = 1;
48 
49     /** Default timer to dismiss the dialog. */
50     private static final long DEFAULT_TIMER = 5 * 60 * 1000;
51 
52     /** To remember the exact time when the timer should fire. */
53     private static final String TIMER_FIRE = "timer_fire";
54 
55     private ContentValues mMessageValues = null;
56 
57     /** Is the message read. */
58     private boolean mRead = false;
59 
60     /** The timer to dismiss the dialog automatically. */
61     private long mTimerSet = 0;
62     private AlertDialog mDialog = null;
63 
64     private ArrayList<ContentValues> mMessageQueue = null;
65 
66     private final Handler mHandler = new Handler() {
67         @Override
68         public void handleMessage(final Message msg) {
69             // Do not handle an invalid message.
70             if (msg.what == ON_AUTO_SAVE) {
71                 mRead = false;
72                 mDialog.dismiss();
73                 saveMessage();
74                 processNextMessage();
75             }
76         }
77     };
78 
queueMsgFromIntent(final Intent msgIntent)79     private boolean queueMsgFromIntent(final Intent msgIntent) {
80         final ContentValues messageValues =
81                 msgIntent.getParcelableExtra(UIIntents.UI_INTENT_EXTRA_MESSAGE_VALUES);
82         // that takes the format argument is a hidden API right now.
83         final String message = messageValues.getAsString(Sms.BODY);
84         if (TextUtils.isEmpty(message)) {
85             if (mMessageQueue.size() == 0) {
86                 finish();
87             }
88             return false;
89         }
90         mMessageQueue.add(messageValues);
91         return true;
92     }
93 
processNextMessage()94     private void processNextMessage() {
95         if (mMessageQueue.size() > 0) {
96             mMessageQueue.remove(0);
97         }
98         if (mMessageQueue.size() == 0) {
99             finish();
100         } else {
101             displayZeroMessage(mMessageQueue.get(0));
102         }
103     }
104 
saveMessage()105     private void saveMessage() {
106         mMessageValues.put(Sms.Inbox.READ, mRead ? Integer.valueOf(1) : Integer.valueOf(0));
107         final ReceiveSmsMessageAction action = new ReceiveSmsMessageAction(mMessageValues);
108         action.start();
109     }
110 
111     @Override
onCreate(final Bundle icicle)112     protected void onCreate(final Bundle icicle) {
113         super.onCreate(icicle);
114         requestWindowFeature(Window.FEATURE_NO_TITLE);
115 
116         if (mMessageQueue == null) {
117             mMessageQueue = new ArrayList<ContentValues>();
118         }
119         if (!queueMsgFromIntent(getIntent())) {
120             return;
121         }
122         Assert.isTrue(mMessageQueue.size() == 1);
123         if (mMessageQueue.size() == 1) {
124             displayZeroMessage(mMessageQueue.get(0));
125         }
126 
127         if (icicle != null) {
128             mTimerSet = icicle.getLong(TIMER_FIRE, mTimerSet);
129         }
130     }
131 
displayZeroMessage(final ContentValues messageValues)132     private void displayZeroMessage(final ContentValues messageValues) {
133         /* This'll be used by the save action */
134         mMessageValues = messageValues;
135         final String message = messageValues.getAsString(Sms.BODY);;
136 
137         mDialog = new AlertDialog.Builder(this).setMessage(message)
138             .setPositiveButton(R.string.save, mSaveListener)
139             .setNegativeButton(android.R.string.cancel, mCancelListener)
140             .setTitle(R.string.class_0_message_activity)
141             .setCancelable(false).show();
142         final long now = SystemClock.uptimeMillis();
143         mTimerSet = now + DEFAULT_TIMER;
144     }
145 
146     @Override
onNewIntent(final Intent msgIntent)147     protected void onNewIntent(final Intent msgIntent) {
148         // Running with another visible message, queue this one
149         queueMsgFromIntent(msgIntent);
150     }
151 
152     @Override
onStart()153     protected void onStart() {
154         super.onStart();
155         final long now = SystemClock.uptimeMillis();
156         if (mTimerSet <= now) {
157             // Save the message if the timer already expired.
158             mHandler.sendEmptyMessage(ON_AUTO_SAVE);
159         } else {
160             mHandler.sendEmptyMessageAtTime(ON_AUTO_SAVE, mTimerSet);
161             if (VERBOSE) {
162                 Log.d(TAG, "onRestart time = " + Long.toString(mTimerSet) + " "
163                         + this.toString());
164             }
165         }
166     }
167 
168     @Override
onSaveInstanceState(final Bundle outState)169     protected void onSaveInstanceState(final Bundle outState) {
170         super.onSaveInstanceState(outState);
171         outState.putLong(TIMER_FIRE, mTimerSet);
172         if (VERBOSE) {
173             Log.d(TAG, "onSaveInstanceState time = " + Long.toString(mTimerSet)
174                     + " " + this.toString());
175         }
176     }
177 
178     @Override
onStop()179     protected void onStop() {
180         super.onStop();
181         mHandler.removeMessages(ON_AUTO_SAVE);
182         if (VERBOSE) {
183             Log.d(TAG, "onStop time = " + Long.toString(mTimerSet)
184                     + " " + this.toString());
185         }
186     }
187 
188     private final OnClickListener mCancelListener = new OnClickListener() {
189         @Override
190         public void onClick(final DialogInterface dialog, final int whichButton) {
191             dialog.dismiss();
192             processNextMessage();
193         }
194     };
195 
196     private final OnClickListener mSaveListener = new OnClickListener() {
197         @Override
198         public void onClick(final DialogInterface dialog, final int whichButton) {
199             mRead = true;
200             saveMessage();
201             dialog.dismiss();
202             processNextMessage();
203         }
204     };
205 }
206