1/*
2 * Copyright (C) 2008 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.basicsmsreceiver;
18
19import java.util.ArrayList;
20import java.util.List;
21
22import android.app.Activity;
23import android.app.PendingIntent;
24import android.content.BroadcastReceiver;
25import android.content.Context;
26import android.content.Intent;
27import android.content.IntentFilter;
28import android.database.Cursor;
29import android.graphics.Color;
30import android.os.Bundle;
31import android.provider.Telephony;
32import android.telephony.SmsManager;
33import android.telephony.SmsMessage;
34import android.telephony.TelephonyManager;
35import android.test.ActivityInstrumentationTestCase2;
36import android.test.suitebuilder.annotation.MediumTest;
37import android.test.suitebuilder.annotation.SmallTest;
38import android.test.suitebuilder.annotation.LargeTest;
39import android.util.Log;
40
41/**
42 * Various instrumentation tests for BasicSmsReceiver.
43 *
44 * To run this test: runtest basicsmsreceiver
45 *
46 * TODO: write tests that verify that notifications get created. As of now, I don't see a way
47 * to query the NotificationManager for what notifications are there. I only see methods to
48 * post and cancel notifications.
49 *
50 */
51public class DialogSmsDisplayTests
52        extends ActivityInstrumentationTestCase2<DialogSmsDisplay> {
53
54    private boolean mHasSms;
55    private String mMyNumber;       // phone number of this device
56    public static final String ACTION_SMS_SENT =
57        "com.android.basicsmsreceiver.tests.SMS_SENT_ACTION";
58    private static String TAG = "DialogSmsDisplayTests";
59    private List<String> mReceivedMessages = new ArrayList<String>();
60    private String mReceivedSender;
61    private DialogSmsDisplay dialogSmsDisplayActivity;
62    private int mMessageReceivedCount;
63    private BroadcastReceiver mSmsSenderReceiver;
64    private BroadcastReceiver mSmsReceiverReceiver;
65
66    public DialogSmsDisplayTests() {
67        super("com.android.basicsmsreceiver", DialogSmsDisplay.class);
68        Log.i(TAG, "DialogSmsDisplayTests");
69    }
70
71    @Override
72    protected void setUp() throws Exception {
73        super.setUp();
74
75        dialogSmsDisplayActivity = (DialogSmsDisplay)getActivity();
76
77        TelephonyManager telephonyManager = ((TelephonyManager)dialogSmsDisplayActivity
78                .getSystemService(Context.TELEPHONY_SERVICE));
79        mHasSms = true;     //telephonyManager.isSmsCapable();
80        mMyNumber = telephonyManager.getLine1Number();
81
82        Log.i(TAG, "hasSms: " + mHasSms + " my number: " + mMyNumber);
83
84        assertTrue("SMS must be enabled on the device", mHasSms);
85        assertNotNull("Device does not have a phone number", mMyNumber);
86
87        if (mHasSms) {
88            // Register broadcast receivers for SMS sent and delivered intents
89            mSmsSenderReceiver = new BroadcastReceiver() {
90                @Override
91                public void onReceive(Context context, Intent intent) {
92                    String message = null;
93                    boolean error = true;
94                    switch (getResultCode()) {
95                        case Activity.RESULT_OK:
96                            message = "Message sent!";
97                            error = false;
98                            break;
99                        case SmsManager.RESULT_ERROR_GENERIC_FAILURE:
100                            message = "Error.";
101                            break;
102                        case SmsManager.RESULT_ERROR_NO_SERVICE:
103                            message = "Error: No SMS service.";
104                            break;
105                        case SmsManager.RESULT_ERROR_NULL_PDU:
106                            message = "Error: Null PDU.";
107                            break;
108                        case SmsManager.RESULT_ERROR_RADIO_OFF:
109                            message = "Error: Radio off.";
110                            break;
111                    }
112                    assertFalse(message, error);
113                }
114            };
115            dialogSmsDisplayActivity.registerReceiver(mSmsSenderReceiver,
116                    new IntentFilter(ACTION_SMS_SENT));
117
118            // Register broadcast receivers for received SMS
119            mSmsReceiverReceiver = new BroadcastReceiver() {
120                @Override
121                public void onReceive(Context context, Intent intent) {
122                    Bundle extras = intent.getExtras();
123                    Log.i(TAG, "onReceive");
124                    if (extras == null)
125                        return;
126
127                    Object[] pdus = (Object[]) extras.get("pdus");
128
129                    for (int i = 0; i < pdus.length; i++) {
130                        SmsMessage message = SmsMessage.createFromPdu((byte[]) pdus[i]);
131                        String sender = message.getOriginatingAddress();
132                        if (mReceivedSender != null) {
133                            assertEquals(mReceivedSender, sender);
134                        } else {
135                            mReceivedSender = sender;
136                        }
137                        mReceivedMessages.add(message.getMessageBody().toString());
138
139                        Log.i(TAG, "From: " + mReceivedSender + " message: " +
140                                mReceivedMessages.get(mReceivedMessages.size() - 1));
141                    }
142                }
143            };
144            dialogSmsDisplayActivity.registerReceiver(mSmsReceiverReceiver,
145                    new IntentFilter(Telephony.Sms.Intents.SMS_RECEIVED_ACTION));
146        }
147    }
148
149    @Override
150    protected void tearDown() throws Exception {
151        if (mSmsSenderReceiver != null) {
152            dialogSmsDisplayActivity.unregisterReceiver(mSmsSenderReceiver);
153            mSmsSenderReceiver = null;
154        }
155        if (mSmsReceiverReceiver != null) {
156            dialogSmsDisplayActivity.unregisterReceiver(mSmsReceiverReceiver);
157            mSmsReceiverReceiver = null;
158        }
159        super.tearDown();
160    }
161
162    // Returns the broken up list of messages for long messages or the original message in
163    // element 0.
164    private List<String> sendSmsMessageInternal(String messageOut) {
165        if (!mHasSms) {
166            fail("no sms on device");
167            return null;
168        }
169        SmsManager sms = SmsManager.getDefault();
170
171        List<String> messages = sms.divideMessage(messageOut);
172        mMessageReceivedCount = 0;
173        mReceivedSender = null;
174        mReceivedMessages.clear();
175
176        for (String message : messages) {
177            Log.i(TAG, "sendSmsMessage: " + messageOut + " to: " + mMyNumber);
178            sms.sendTextMessage(mMyNumber, null, message, PendingIntent.getBroadcast(
179                    dialogSmsDisplayActivity, 0, new Intent(ACTION_SMS_SENT), 0), null);
180        }
181        return messages;
182    }
183
184    // returns true if "messageCount" sms messages are received, false if timeout
185    private boolean waitForSms(int messageCount) {
186        // wait up to two minutes for the sent message to be received
187        long now = System.currentTimeMillis();
188        boolean success = true;
189        Log.i(TAG, "waitForSms -- waiting for: " + messageCount + " parts");
190        while (mReceivedMessages.size() < messageCount) {
191            try {
192                Thread.sleep(1000);
193            } catch (Exception e) {
194            }
195            if (System.currentTimeMillis() - now > 1000 * 2 * 60) {
196                // Give up after two minutes
197                success = false;
198                break;
199            }
200        }
201        if (success) {
202            // Wait 5 seconds for the dialog to launch and update
203            try {
204                Thread.sleep(5000);
205            } catch (Exception e) {
206            }
207        }
208        return success;
209    }
210
211    private void sendMessageTest(String message) {
212        List<String> messages = sendSmsMessageInternal(message);
213        Log.i(TAG, "sendMessageTest -- message broken into " + messages.size() + "parts");
214
215        boolean receivedSms = waitForSms(messages.size());
216        assertTrue("sms not received after two minutes", receivedSms);
217
218        // Check to see if message/# matches
219        assertEquals(mMyNumber, mReceivedSender);
220        assertEquals(messages.size(), mReceivedMessages.size());
221        int i = 0;
222        for (String messageFrag : messages) {
223            assertEquals(messageFrag, mReceivedMessages.get(i++));
224        }
225    }
226
227    public void testSendingSmallSmsMessage() {
228        sendMessageTest("This is a regular size message that might be sent");
229    }
230
231    public void testSendingLargeSmsMessage() {
232        sendMessageTest("This is a long long message. " +
233                "This is a long long message. " +
234                "This is a long long message. " +
235                "This is a long long message. " +
236                "This is a long long message. " +
237                "This is a long long message. " +
238                "This is a long long message. " +
239                "This is a long long message. " +
240                "This is a long long message. " +
241                "This is a long long message. " +
242                "This is a long long message. " +
243                "This is a long long message. " +
244                "This is a long long message. " +
245                "This is a long long message. " +
246                "This is a long long message. " +
247                "This is a long long message. " +
248                "This is a long long message. " +
249                "This is a long long message. " +
250                "This is a long long message. " +
251                "This is a long long message. " +
252                "This is a long long message. " +
253                "This is a long long message. " +
254                "This is a long long message. " +
255                "This is a long long message. " +
256                "This is a long long message. " +
257                "This is a long long message. " +
258                "This is a long long message. " +
259                "This is a long long message. ");
260    }
261
262    public void testOnNewIntentSmall() {
263        // Test a small message and a non-numeric phone number
264        sendOnNewIntent("this is a big fat test", "xyzzy", 2000);
265    }
266
267    public void testOnNewIntentLarge() {
268        // A long message like this should never really happen because SMS messages are limited
269        // to about 140 characters.
270        sendOnNewIntent("now is the time for all good men to come to the aid of their country1" +
271                "now is the time for all good men to come to the aid of their country2" +
272                "now is the time for all good men to come to the aid of their country3",
273                "513-891-7823", 2001);
274    }
275
276    public void sendOnNewIntent(String message, String dest, int notificationId) {
277        Intent di = new Intent();
278        di.setClass(dialogSmsDisplayActivity, DialogSmsDisplay.class);
279        di.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP |
280                Intent.FLAG_ACTIVITY_CLEAR_TOP);
281        di.putExtra(DialogSmsDisplay.SMS_FROM_ADDRESS_EXTRA, dest);
282        di.putExtra(DialogSmsDisplay.SMS_MESSAGE_EXTRA, message);
283        di.putExtra(DialogSmsDisplay.SMS_NOTIFICATION_ID_EXTRA, notificationId);
284        dialogSmsDisplayActivity.onNewIntent(di);
285
286        // Check to see if message/# matches
287        assertEquals(dest, dialogSmsDisplayActivity.mFromAddress);
288        assertEquals(message, dialogSmsDisplayActivity.mMessage);
289    }
290}
291