132b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajan/* 22f2dba9413a3f14da0bcf45031986eb78f007dd8fionaxu * Copyright (C) 2016 The Android Open Source Project 332b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajan * 432b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajan * Licensed under the Apache License, Version 2.0 (the "License"); 532b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajan * you may not use this file except in compliance with the License. 632b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajan * You may obtain a copy of the License at 732b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajan * 832b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajan * http://www.apache.org/licenses/LICENSE-2.0 932b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajan * 1032b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajan * Unless required by applicable law or agreed to in writing, software 1132b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajan * distributed under the License is distributed on an "AS IS" BASIS, 1232b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajan * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1332b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajan * See the License for the specific language governing permissions and 1432b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajan * limitations under the License. 1532b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajan */ 1632b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajan 1732b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajanpackage com.android.internal.telephony.gsm; 1832b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajan 195eccb26b2bcf3a51326596e1b0bb49b073d2f9fcAbhijith Shastryimport android.content.BroadcastReceiver; 20e2435e2d37c991bd6209a90cd884b5102939872eAbhijith Shastryimport android.content.ContentValues; 21e2435e2d37c991bd6209a90cd884b5102939872eAbhijith Shastryimport android.content.Context; 22e2435e2d37c991bd6209a90cd884b5102939872eAbhijith Shastryimport android.content.Intent; 23e2435e2d37c991bd6209a90cd884b5102939872eAbhijith Shastryimport android.content.IntentFilter; 24e2435e2d37c991bd6209a90cd884b5102939872eAbhijith Shastryimport android.database.Cursor; 25e2435e2d37c991bd6209a90cd884b5102939872eAbhijith Shastryimport android.database.MatrixCursor; 26e2435e2d37c991bd6209a90cd884b5102939872eAbhijith Shastryimport android.net.Uri; 27e2435e2d37c991bd6209a90cd884b5102939872eAbhijith Shastryimport android.os.AsyncResult; 28e2435e2d37c991bd6209a90cd884b5102939872eAbhijith Shastryimport android.os.Bundle; 29655bae990bdd7e4584491def4d30692e6173779cfionaxuimport android.os.Handler; 30655bae990bdd7e4584491def4d30692e6173779cfionaxuimport android.os.HandlerThread; 3132b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajanimport android.os.UserManager; 321bcd7a866ddf8f6f63370c70972f057a4a1ba057Jack Yuimport android.os.RemoteException; 331bcd7a866ddf8f6f63370c70972f057a4a1ba057Jack Yuimport android.os.UserHandle; 34153077e0b2d9ff6f115a0739dac1d64931bffb91Amit Mahajanimport android.provider.Telephony; 356ba18ef5f3733709f16ef03b3d2b2de076b63c3efionaxuimport android.test.mock.MockContentProvider; 366ba18ef5f3733709f16ef03b3d2b2de076b63c3efionaxuimport android.test.mock.MockContentResolver; 37871a2ec0bc8e8198aeb1913e7bf6cb22a7ff3604Amit Mahajanimport android.test.suitebuilder.annotation.MediumTest; 38e2435e2d37c991bd6209a90cd884b5102939872eAbhijith Shastry 39b9d551db1795b30598e2ce98cfae7106788c12d6fionaxuimport com.android.internal.telephony.InboundSmsHandler; 401bcd7a866ddf8f6f63370c70972f057a4a1ba057Jack Yuimport com.android.internal.telephony.InboundSmsTracker; 4132b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajanimport com.android.internal.telephony.SmsBroadcastUndelivered; 4232b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajanimport com.android.internal.telephony.SmsHeader; 43ec6e2f9f13bac23cdfa0de0a56826b21050b6487fionaxuimport com.android.internal.telephony.SmsStorageMonitor; 44e2435e2d37c991bd6209a90cd884b5102939872eAbhijith Shastryimport com.android.internal.telephony.TelephonyTest; 4532b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajanimport com.android.internal.telephony.cdma.CdmaInboundSmsHandler; 461fe1dbf473755c4e812a1218f331759eccacb447Jack Yuimport com.android.internal.util.HexDump; 47e2435e2d37c991bd6209a90cd884b5102939872eAbhijith Shastryimport com.android.internal.util.IState; 48e2435e2d37c991bd6209a90cd884b5102939872eAbhijith Shastryimport com.android.internal.util.StateMachine; 4932b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajan 50655bae990bdd7e4584491def4d30692e6173779cfionaxuimport static com.android.internal.telephony.TelephonyTestUtils.waitForMs; 51f152b32a20be664788536a223b9ac7a52f69e4ddAmit Mahajanimport static org.junit.Assert.*; 5232b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajanimport static org.mockito.Mockito.*; 53f9b150b221db15e88b97a0b9c0971ca3c71c0313fionaxu 54f9b150b221db15e88b97a0b9c0971ca3c71c0313fionaxuimport org.junit.After; 5575ba09a17a669f4906268088a769836aa87d8241fionaxuimport org.junit.Before; 5632b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajanimport org.junit.Test; 5732b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajanimport org.mockito.ArgumentCaptor; 58dbe4d7749d5524be575f629486874acdae721138Amit Mahajanimport org.mockito.Mock; 5932b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajan 60f9b150b221db15e88b97a0b9c0971ca3c71c0313fionaxuimport java.lang.reflect.Method; 61f9b150b221db15e88b97a0b9c0971ca3c71c0313fionaxuimport java.util.ArrayList; 62ec6e2f9f13bac23cdfa0de0a56826b21050b6487fionaxuimport java.util.List; 6332b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajan 6432b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajanpublic class GsmInboundSmsHandlerTest extends TelephonyTest { 6532b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajan @Mock 66655bae990bdd7e4584491def4d30692e6173779cfionaxu private SmsStorageMonitor mSmsStorageMonitor; 67e2435e2d37c991bd6209a90cd884b5102939872eAbhijith Shastry @Mock 68153077e0b2d9ff6f115a0739dac1d64931bffb91Amit Mahajan private android.telephony.SmsMessage mSmsMessage; 69153077e0b2d9ff6f115a0739dac1d64931bffb91Amit Mahajan @Mock 7078867803826b15ff95c8ee8c7c6f65dfb7ad258fAmit Mahajan private SmsMessage mGsmSmsMessage; 7132b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajan @Mock 7232b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajan private SmsHeader mSmsHeader; 7332b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajan @Mock 7432b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajan private InboundSmsTracker mInboundSmsTrackerPart1; 75e2435e2d37c991bd6209a90cd884b5102939872eAbhijith Shastry @Mock 76e2435e2d37c991bd6209a90cd884b5102939872eAbhijith Shastry private InboundSmsTracker mInboundSmsTrackerPart2; 7732b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajan @Mock 7832b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajan private CdmaInboundSmsHandler mCdmaInboundSmsHandler; 7932b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajan 80e2435e2d37c991bd6209a90cd884b5102939872eAbhijith Shastry private GsmInboundSmsHandler mGsmInboundSmsHandler; 819c96807d990cdd3f4bb2d3f0fd56a1e78a95b353Jack Yu 829c96807d990cdd3f4bb2d3f0fd56a1e78a95b353Jack Yu private FakeSmsContentProvider mContentProvider; 83e2435e2d37c991bd6209a90cd884b5102939872eAbhijith Shastry private static final Uri sRawUri = Uri.withAppendedPath(Telephony.Sms.CONTENT_URI, "raw"); 8432b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajan private static final Uri sRawUriPermanentDelete = 8532b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajan Uri.withAppendedPath(Telephony.Sms.CONTENT_URI, "raw/permanentDelete"); 8632b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajan 8732b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajan private ContentValues mInboundSmsTrackerCV = new ContentValues(); 8832b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajan // For multi-part SMS 89f152b32a20be664788536a223b9ac7a52f69e4ddAmit Mahajan private ContentValues mInboundSmsTrackerCVPart1; 9032b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajan private ContentValues mInboundSmsTrackerCVPart2; 91f9b150b221db15e88b97a0b9c0971ca3c71c0313fionaxu private String mMessageBody = "This is the message body of a single-part message"; 92f9b150b221db15e88b97a0b9c0971ca3c71c0313fionaxu private String mMessageBodyPart1 = "This is the first part of a multi-part message"; 9332b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajan private String mMessageBodyPart2 = "This is the second part of a multi-part message"; 9432b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajan 9532b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajan byte[] mSmsPdu = new byte[]{(byte)0xFF, (byte)0xFF, (byte)0xFF}; 9632b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajan 97f9b150b221db15e88b97a0b9c0971ca3c71c0313fionaxu public static class FakeSmsContentProvider extends MockContentProvider { 98f9b150b221db15e88b97a0b9c0971ca3c71c0313fionaxu private String[] mRawColumns = {"_id", 9932b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajan "date", 10032b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajan "reference_number", 10132b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajan "count", 10232b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajan "sequence", 10332b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajan "destination_port", 10432b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajan "address", 10532b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajan "sub_id", 10632b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajan "pdu", 10732b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajan "deleted", 10832b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajan "message_body"}; 10932b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajan private List<ArrayList<Object>> mListOfRows = new ArrayList<ArrayList<Object>>(); 11032b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajan private int mNumRows = 0; 11132b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajan 11232b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajan private int getColumnIndex(String columnName) { 11332b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajan int i = 0; 11432b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajan for (String s : mRawColumns) { 11575ba09a17a669f4906268088a769836aa87d8241fionaxu if (s.equals(columnName)) { 11632b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajan break; 11732b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajan } 11832b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajan i++; 1194a9f066fbcbd20e2ea3ca3cbc914f81b230e3825fionaxu } 1204a9f066fbcbd20e2ea3ca3cbc914f81b230e3825fionaxu return i; 121f9b150b221db15e88b97a0b9c0971ca3c71c0313fionaxu } 122f9b150b221db15e88b97a0b9c0971ca3c71c0313fionaxu 123f9b150b221db15e88b97a0b9c0971ca3c71c0313fionaxu @Override 124f9b150b221db15e88b97a0b9c0971ca3c71c0313fionaxu public int delete(Uri uri, String selection, String[] selectionArgs) { 12575ba09a17a669f4906268088a769836aa87d8241fionaxu int count = 0; 12675ba09a17a669f4906268088a769836aa87d8241fionaxu if (mNumRows > 0) { 12732b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajan // parse selection and selectionArgs 12832b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajan SelectionParams selectionParams = new SelectionParams(); 12932b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajan selectionParams.parseSelectionParams(selection, selectionArgs); 13032b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajan 13132b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajan List<Integer> deleteRows = new ArrayList<Integer>(); 13232b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajan int i = -1; 13332b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajan for (ArrayList<Object> row : mListOfRows) { 13460a81bdb47cf64972c8edf5b0c51e8059765e5a0Amit Mahajan i++; 13560a81bdb47cf64972c8edf5b0c51e8059765e5a0Amit Mahajan // filter based on selection parameters if needed 13660a81bdb47cf64972c8edf5b0c51e8059765e5a0Amit Mahajan if (selection != null) { 13760a81bdb47cf64972c8edf5b0c51e8059765e5a0Amit Mahajan if (!selectionParams.isMatch(row)) { 138f152b32a20be664788536a223b9ac7a52f69e4ddAmit Mahajan continue; 139153077e0b2d9ff6f115a0739dac1d64931bffb91Amit Mahajan } 14078867803826b15ff95c8ee8c7c6f65dfb7ad258fAmit Mahajan } 141153077e0b2d9ff6f115a0739dac1d64931bffb91Amit Mahajan if (uri.compareTo(sRawUri) == 0) { 142153077e0b2d9ff6f115a0739dac1d64931bffb91Amit Mahajan row.set(getColumnIndex("deleted"), "1"); 143153077e0b2d9ff6f115a0739dac1d64931bffb91Amit Mahajan } else { 144153077e0b2d9ff6f115a0739dac1d64931bffb91Amit Mahajan // save index for removal 145153077e0b2d9ff6f115a0739dac1d64931bffb91Amit Mahajan deleteRows.add(i); 146153077e0b2d9ff6f115a0739dac1d64931bffb91Amit Mahajan } 147153077e0b2d9ff6f115a0739dac1d64931bffb91Amit Mahajan count++; 148153077e0b2d9ff6f115a0739dac1d64931bffb91Amit Mahajan } 149153077e0b2d9ff6f115a0739dac1d64931bffb91Amit Mahajan 150655bae990bdd7e4584491def4d30692e6173779cfionaxu if (uri.compareTo(sRawUriPermanentDelete) == 0) { 151655bae990bdd7e4584491def4d30692e6173779cfionaxu for (i = deleteRows.size() - 1; i >= 0; i--) { 152655bae990bdd7e4584491def4d30692e6173779cfionaxu mListOfRows.remove(i); 153217d4d9562a9476cf579dfc409b1278a02b18b87Amit Mahajan } 154217d4d9562a9476cf579dfc409b1278a02b18b87Amit Mahajan } 155217d4d9562a9476cf579dfc409b1278a02b18b87Amit Mahajan } 15627f471647b2da3ff50620a766c048ebef8d45ae1Amit Mahajan return count; 15727f471647b2da3ff50620a766c048ebef8d45ae1Amit Mahajan } 1581bcd7a866ddf8f6f63370c70972f057a4a1ba057Jack Yu 1591bcd7a866ddf8f6f63370c70972f057a4a1ba057Jack Yu @Override 1601bcd7a866ddf8f6f63370c70972f057a4a1ba057Jack Yu public Uri insert(Uri uri, ContentValues values) { 1611bcd7a866ddf8f6f63370c70972f057a4a1ba057Jack Yu Uri newUri = null; 1626ba18ef5f3733709f16ef03b3d2b2de076b63c3efionaxu if (uri.compareTo(sRawUri) == 0) { 1636ba18ef5f3733709f16ef03b3d2b2de076b63c3efionaxu if (values != null) { 1646ba18ef5f3733709f16ef03b3d2b2de076b63c3efionaxu mListOfRows.add(convertRawCVtoArrayList(values)); 1656ba18ef5f3733709f16ef03b3d2b2de076b63c3efionaxu mNumRows++; 1666ba18ef5f3733709f16ef03b3d2b2de076b63c3efionaxu newUri = Uri.withAppendedPath(uri, "" + mNumRows); 1676ba18ef5f3733709f16ef03b3d2b2de076b63c3efionaxu } 168dbe4d7749d5524be575f629486874acdae721138Amit Mahajan } 169dbe4d7749d5524be575f629486874acdae721138Amit Mahajan logd("insert called, new numRows: " + mNumRows); 1707a1c1b02c8603c2bf2f3b401facb389528180eedPavel Zhamaitsiak return newUri; 1717a1c1b02c8603c2bf2f3b401facb389528180eedPavel Zhamaitsiak } 17232b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajan 173af59a35e945d60fc9ffb305c494a695b35b8a942fionaxu private ArrayList<Object> convertRawCVtoArrayList(ContentValues values) { 17432b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajan ArrayList<Object> newRow = new ArrayList<>(); 17532b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajan for (String key : mRawColumns) { 176f152b32a20be664788536a223b9ac7a52f69e4ddAmit Mahajan if (values.containsKey(key)) { 177e2435e2d37c991bd6209a90cd884b5102939872eAbhijith Shastry newRow.add(values.getAsString(key)); 178f152b32a20be664788536a223b9ac7a52f69e4ddAmit Mahajan } else if (key.equals("_id")) { 179f152b32a20be664788536a223b9ac7a52f69e4ddAmit Mahajan newRow.add(mNumRows + 1); 180ec6e2f9f13bac23cdfa0de0a56826b21050b6487fionaxu } else if (key.equals("deleted")) { 181ec6e2f9f13bac23cdfa0de0a56826b21050b6487fionaxu newRow.add("0"); 182f152b32a20be664788536a223b9ac7a52f69e4ddAmit Mahajan } else { 18375ba09a17a669f4906268088a769836aa87d8241fionaxu newRow.add(null); 1849c96807d990cdd3f4bb2d3f0fd56a1e78a95b353Jack Yu } 1859c96807d990cdd3f4bb2d3f0fd56a1e78a95b353Jack Yu } 1869c96807d990cdd3f4bb2d3f0fd56a1e78a95b353Jack Yu return newRow; 1879c96807d990cdd3f4bb2d3f0fd56a1e78a95b353Jack Yu } 1889c96807d990cdd3f4bb2d3f0fd56a1e78a95b353Jack Yu 1899c96807d990cdd3f4bb2d3f0fd56a1e78a95b353Jack Yu private class SelectionParams { 1909c96807d990cdd3f4bb2d3f0fd56a1e78a95b353Jack Yu String[] paramName = null; 1919c96807d990cdd3f4bb2d3f0fd56a1e78a95b353Jack Yu String[] paramValue = null; 1929c96807d990cdd3f4bb2d3f0fd56a1e78a95b353Jack Yu 1939c96807d990cdd3f4bb2d3f0fd56a1e78a95b353Jack Yu private void parseSelectionParams(String selection, String[] selectionArgs) { 1949c96807d990cdd3f4bb2d3f0fd56a1e78a95b353Jack Yu if (selection != null) { 1959c96807d990cdd3f4bb2d3f0fd56a1e78a95b353Jack Yu selection = selection.toLowerCase(); 1969c96807d990cdd3f4bb2d3f0fd56a1e78a95b353Jack Yu String[] selectionParams = selection.toLowerCase().split("and"); 1979c96807d990cdd3f4bb2d3f0fd56a1e78a95b353Jack Yu int i = 0; 1989c96807d990cdd3f4bb2d3f0fd56a1e78a95b353Jack Yu int j = 0; 1999c96807d990cdd3f4bb2d3f0fd56a1e78a95b353Jack Yu paramName = new String[selectionParams.length]; 2009c96807d990cdd3f4bb2d3f0fd56a1e78a95b353Jack Yu paramValue = new String[selectionParams.length]; 2019c96807d990cdd3f4bb2d3f0fd56a1e78a95b353Jack Yu for (String param : selectionParams) { 2029c96807d990cdd3f4bb2d3f0fd56a1e78a95b353Jack Yu String[] paramWithArg = param.split("="); 2039c96807d990cdd3f4bb2d3f0fd56a1e78a95b353Jack Yu paramName[i] = paramWithArg[0].trim(); 2049c96807d990cdd3f4bb2d3f0fd56a1e78a95b353Jack Yu if (param.contains("?")) { 2059c96807d990cdd3f4bb2d3f0fd56a1e78a95b353Jack Yu paramValue[i] = selectionArgs[j]; 2069c96807d990cdd3f4bb2d3f0fd56a1e78a95b353Jack Yu j++; 2079c96807d990cdd3f4bb2d3f0fd56a1e78a95b353Jack Yu } else { 2089c96807d990cdd3f4bb2d3f0fd56a1e78a95b353Jack Yu paramValue[i] = paramWithArg[1].trim(); 2099c96807d990cdd3f4bb2d3f0fd56a1e78a95b353Jack Yu } 210655bae990bdd7e4584491def4d30692e6173779cfionaxu //logd(paramName[i] + " = " + paramValue[i]); 211655bae990bdd7e4584491def4d30692e6173779cfionaxu i++; 2129c96807d990cdd3f4bb2d3f0fd56a1e78a95b353Jack Yu } 2139c96807d990cdd3f4bb2d3f0fd56a1e78a95b353Jack Yu } 21432b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajan } 21532b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajan 216655bae990bdd7e4584491def4d30692e6173779cfionaxu private boolean isMatch(ArrayList<Object> row) { 21732b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajan for (int i = 0; i < paramName.length; i++) { 21832b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajan int columnIndex = 0; 21932b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajan for (String columnName : mRawColumns) { 22032b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajan if (columnName.equals(paramName[i])) { 22132b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajan if ((paramValue[i] == null && row.get(columnIndex) != null) || 22232b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajan (paramValue[i] != null && 22332b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajan !paramValue[i].equals(row.get(columnIndex)))) { 22432b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajan logd("Not a match due to " + columnName + ": " + paramValue[i] + 22532b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajan ", " + row.get(columnIndex)); 22632b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajan return false; 22732b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajan } else { 22832b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajan // move on to next param 22932b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajan break; 23032b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajan } 2319c96807d990cdd3f4bb2d3f0fd56a1e78a95b353Jack Yu } 2329c96807d990cdd3f4bb2d3f0fd56a1e78a95b353Jack Yu columnIndex++; 2339c96807d990cdd3f4bb2d3f0fd56a1e78a95b353Jack Yu } 2349c96807d990cdd3f4bb2d3f0fd56a1e78a95b353Jack Yu } 23521e1b42d578d90611f76c37d58841543821502fdJack Yu return true; 23632b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajan } 2379c96807d990cdd3f4bb2d3f0fd56a1e78a95b353Jack Yu } 2389c96807d990cdd3f4bb2d3f0fd56a1e78a95b353Jack Yu 2399c96807d990cdd3f4bb2d3f0fd56a1e78a95b353Jack Yu @Override 2409c96807d990cdd3f4bb2d3f0fd56a1e78a95b353Jack Yu public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, 2419c96807d990cdd3f4bb2d3f0fd56a1e78a95b353Jack Yu String sortOrder) { 2429c96807d990cdd3f4bb2d3f0fd56a1e78a95b353Jack Yu logd("query called for: " + selection); 2439c96807d990cdd3f4bb2d3f0fd56a1e78a95b353Jack Yu MatrixCursor cursor = new MatrixCursor(projection); 24432b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajan if (mNumRows > 0) { 2459c96807d990cdd3f4bb2d3f0fd56a1e78a95b353Jack Yu // parse selection and selectionArgs 2469c96807d990cdd3f4bb2d3f0fd56a1e78a95b353Jack Yu SelectionParams selectionParams = new SelectionParams(); 2479c96807d990cdd3f4bb2d3f0fd56a1e78a95b353Jack Yu selectionParams.parseSelectionParams(selection, selectionArgs); 2489c96807d990cdd3f4bb2d3f0fd56a1e78a95b353Jack Yu 2499c96807d990cdd3f4bb2d3f0fd56a1e78a95b353Jack Yu for (ArrayList<Object> row : mListOfRows) { 2509c96807d990cdd3f4bb2d3f0fd56a1e78a95b353Jack Yu ArrayList<Object> retRow = new ArrayList<>(); 2519c96807d990cdd3f4bb2d3f0fd56a1e78a95b353Jack Yu // filter based on selection parameters if needed 2529c96807d990cdd3f4bb2d3f0fd56a1e78a95b353Jack Yu if (selection != null) { 2539c96807d990cdd3f4bb2d3f0fd56a1e78a95b353Jack Yu if (!selectionParams.isMatch(row)) { 2549c96807d990cdd3f4bb2d3f0fd56a1e78a95b353Jack Yu continue; 2559c96807d990cdd3f4bb2d3f0fd56a1e78a95b353Jack Yu } 25632b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajan } 2579c96807d990cdd3f4bb2d3f0fd56a1e78a95b353Jack Yu 2589c96807d990cdd3f4bb2d3f0fd56a1e78a95b353Jack Yu for (String columnName : projection) { 25932b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajan int columnIndex = getColumnIndex(columnName); 2609c96807d990cdd3f4bb2d3f0fd56a1e78a95b353Jack Yu retRow.add(row.get(columnIndex)); 2619c96807d990cdd3f4bb2d3f0fd56a1e78a95b353Jack Yu } 2629c96807d990cdd3f4bb2d3f0fd56a1e78a95b353Jack Yu cursor.addRow(retRow); 2639c96807d990cdd3f4bb2d3f0fd56a1e78a95b353Jack Yu } 2649c96807d990cdd3f4bb2d3f0fd56a1e78a95b353Jack Yu } 2659c96807d990cdd3f4bb2d3f0fd56a1e78a95b353Jack Yu if (cursor != null) { 266f152b32a20be664788536a223b9ac7a52f69e4ddAmit Mahajan logd("returning rows: " + cursor.getCount()); 2679c96807d990cdd3f4bb2d3f0fd56a1e78a95b353Jack Yu } 2689c96807d990cdd3f4bb2d3f0fd56a1e78a95b353Jack Yu return cursor; 2699c96807d990cdd3f4bb2d3f0fd56a1e78a95b353Jack Yu } 27032b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajan 2719c96807d990cdd3f4bb2d3f0fd56a1e78a95b353Jack Yu @Override 2729c96807d990cdd3f4bb2d3f0fd56a1e78a95b353Jack Yu public Bundle call(String method, String request, Bundle args) { 2739c96807d990cdd3f4bb2d3f0fd56a1e78a95b353Jack Yu return null; 27421e1b42d578d90611f76c37d58841543821502fdJack Yu } 2759c96807d990cdd3f4bb2d3f0fd56a1e78a95b353Jack Yu } 2769c96807d990cdd3f4bb2d3f0fd56a1e78a95b353Jack Yu 2779c96807d990cdd3f4bb2d3f0fd56a1e78a95b353Jack Yu private class GsmInboundSmsHandlerTestHandler extends HandlerThread { 2789c96807d990cdd3f4bb2d3f0fd56a1e78a95b353Jack Yu 2799c96807d990cdd3f4bb2d3f0fd56a1e78a95b353Jack Yu private GsmInboundSmsHandlerTestHandler(String name) { 2809c96807d990cdd3f4bb2d3f0fd56a1e78a95b353Jack Yu super(name); 2819c96807d990cdd3f4bb2d3f0fd56a1e78a95b353Jack Yu } 2829c96807d990cdd3f4bb2d3f0fd56a1e78a95b353Jack Yu 283655bae990bdd7e4584491def4d30692e6173779cfionaxu @Override 284217d4d9562a9476cf579dfc409b1278a02b18b87Amit Mahajan public void onLooperPrepared() { 2859c96807d990cdd3f4bb2d3f0fd56a1e78a95b353Jack Yu mGsmInboundSmsHandler = GsmInboundSmsHandler.makeInboundSmsHandler(mContext, 2869c96807d990cdd3f4bb2d3f0fd56a1e78a95b353Jack Yu mSmsStorageMonitor, mPhone); 2879c96807d990cdd3f4bb2d3f0fd56a1e78a95b353Jack Yu setReady(true); 2889c96807d990cdd3f4bb2d3f0fd56a1e78a95b353Jack Yu } 289325ea5a0aa71b9ff6134be71a84a7e1a288c70cbJack Yu } 290325ea5a0aa71b9ff6134be71a84a7e1a288c70cbJack Yu 291ec6e2f9f13bac23cdfa0de0a56826b21050b6487fionaxu private IState getCurrentState() { 29232b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajan try { 29332b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajan Method method = StateMachine.class.getDeclaredMethod("getCurrentState"); 29432b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajan method.setAccessible(true); 295f152b32a20be664788536a223b9ac7a52f69e4ddAmit Mahajan return (IState) method.invoke(mGsmInboundSmsHandler); 296e2435e2d37c991bd6209a90cd884b5102939872eAbhijith Shastry } catch (Exception e) { 297e2435e2d37c991bd6209a90cd884b5102939872eAbhijith Shastry fail(e.toString()); 298e2435e2d37c991bd6209a90cd884b5102939872eAbhijith Shastry return null; 29932b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajan } 3009c96807d990cdd3f4bb2d3f0fd56a1e78a95b353Jack Yu } 301af59a35e945d60fc9ffb305c494a695b35b8a942fionaxu 30232b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajan @Before 3039c96807d990cdd3f4bb2d3f0fd56a1e78a95b353Jack Yu public void setUp() throws Exception { 3049c96807d990cdd3f4bb2d3f0fd56a1e78a95b353Jack Yu super.setUp("GsmInboundSmsHandlerTest"); 3051fe1dbf473755c4e812a1218f331759eccacb447Jack Yu 306217d4d9562a9476cf579dfc409b1278a02b18b87Amit Mahajan doReturn(true).when(mTelephonyManager).getSmsReceiveCapableForPhone(anyInt(), anyBoolean()); 307655bae990bdd7e4584491def4d30692e6173779cfionaxu doReturn(true).when(mSmsStorageMonitor).isStorageAvailable(); 308655bae990bdd7e4584491def4d30692e6173779cfionaxu 309655bae990bdd7e4584491def4d30692e6173779cfionaxu UserManager userManager = (UserManager)mContext.getSystemService(Context.USER_SERVICE); 310655bae990bdd7e4584491def4d30692e6173779cfionaxu doReturn(true).when(userManager).isUserUnlocked(); 311655bae990bdd7e4584491def4d30692e6173779cfionaxu 312655bae990bdd7e4584491def4d30692e6173779cfionaxu try { 313655bae990bdd7e4584491def4d30692e6173779cfionaxu doReturn(new int[]{UserHandle.USER_SYSTEM}).when(mIActivityManager).getRunningUserIds(); 314655bae990bdd7e4584491def4d30692e6173779cfionaxu } catch (RemoteException re) { 315655bae990bdd7e4584491def4d30692e6173779cfionaxu fail("Unexpected RemoteException: " + re.getStackTrace()); 316655bae990bdd7e4584491def4d30692e6173779cfionaxu } 317655bae990bdd7e4584491def4d30692e6173779cfionaxu 318655bae990bdd7e4584491def4d30692e6173779cfionaxu mSmsMessage.mWrappedSmsMessage = mGsmSmsMessage; 31927f471647b2da3ff50620a766c048ebef8d45ae1Amit Mahajan mInboundSmsTrackerCV.put("destination_port", 1 << 16); 32027f471647b2da3ff50620a766c048ebef8d45ae1Amit Mahajan mInboundSmsTrackerCV.put("pdu", HexDump.toHexString(mSmsPdu)); 3216e4abd849e12860a7459f7ec74496ca02b9d7ee0Amit Mahajan mInboundSmsTrackerCV.put("address", "1234567890"); 32227f471647b2da3ff50620a766c048ebef8d45ae1Amit Mahajan mInboundSmsTrackerCV.put("reference_number", 1); 32327f471647b2da3ff50620a766c048ebef8d45ae1Amit Mahajan mInboundSmsTrackerCV.put("sequence", 1); 3246e4abd849e12860a7459f7ec74496ca02b9d7ee0Amit Mahajan mInboundSmsTrackerCV.put("count", 1); 325871a2ec0bc8e8198aeb1913e7bf6cb22a7ff3604Amit Mahajan mInboundSmsTrackerCV.put("date", System.currentTimeMillis()); 326871a2ec0bc8e8198aeb1913e7bf6cb22a7ff3604Amit Mahajan mInboundSmsTrackerCV.put("message_body", mMessageBody); 327ecac744a4e585e3c7af95ffa06fa3e711131200cAmit Mahajan 328ecac744a4e585e3c7af95ffa06fa3e711131200cAmit Mahajan doReturn(1).when(mInboundSmsTracker).getMessageCount(); 329655bae990bdd7e4584491def4d30692e6173779cfionaxu doReturn(1).when(mInboundSmsTracker).getReferenceNumber(); 330655bae990bdd7e4584491def4d30692e6173779cfionaxu doReturn("1234567890").when(mInboundSmsTracker).getAddress(); 331b9d551db1795b30598e2ce98cfae7106788c12d6fionaxu doReturn(1).when(mInboundSmsTracker).getSequenceNumber(); 33278867803826b15ff95c8ee8c7c6f65dfb7ad258fAmit Mahajan doReturn(1).when(mInboundSmsTracker).getIndexOffset(); 33327f471647b2da3ff50620a766c048ebef8d45ae1Amit Mahajan doReturn(-1).when(mInboundSmsTracker).getDestPort(); 33427f471647b2da3ff50620a766c048ebef8d45ae1Amit Mahajan doReturn(mMessageBody).when(mInboundSmsTracker).getMessageBody(); 33578867803826b15ff95c8ee8c7c6f65dfb7ad258fAmit Mahajan doReturn(mSmsPdu).when(mInboundSmsTracker).getPdu(); 336217d4d9562a9476cf579dfc409b1278a02b18b87Amit Mahajan doReturn(mInboundSmsTrackerCV.get("date")).when(mInboundSmsTracker).getTimestamp(); 33778867803826b15ff95c8ee8c7c6f65dfb7ad258fAmit Mahajan doReturn(mInboundSmsTrackerCV).when(mInboundSmsTracker).getContentValues(); 338f9b150b221db15e88b97a0b9c0971ca3c71c0313fionaxu 33978867803826b15ff95c8ee8c7c6f65dfb7ad258fAmit Mahajan mContentProvider = new FakeSmsContentProvider(); 340217d4d9562a9476cf579dfc409b1278a02b18b87Amit Mahajan ((MockContentResolver)mContext.getContentResolver()).addProvider( 341217d4d9562a9476cf579dfc409b1278a02b18b87Amit Mahajan Telephony.Sms.CONTENT_URI.getAuthority(), mContentProvider); 342e415b7b5ae3afec0b7a24d85b930e8cca47499a6fionaxu 343217d4d9562a9476cf579dfc409b1278a02b18b87Amit Mahajan new GsmInboundSmsHandlerTestHandler(TAG).start(); 344217d4d9562a9476cf579dfc409b1278a02b18b87Amit Mahajan waitUntilReady(); 34527b650c406018355a88a41528db7859e232728a0Jack Yu } 34627b650c406018355a88a41528db7859e232728a0Jack Yu 347dbe4d7749d5524be575f629486874acdae721138Amit Mahajan @After 34832b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajan public void tearDown() throws Exception { 349217d4d9562a9476cf579dfc409b1278a02b18b87Amit Mahajan // wait for wakelock to be released; timeout at 10s 350153077e0b2d9ff6f115a0739dac1d64931bffb91Amit Mahajan int i = 0; 351153077e0b2d9ff6f115a0739dac1d64931bffb91Amit Mahajan while (mGsmInboundSmsHandler.getWakeLock().isHeld() && i < 100) { 352153077e0b2d9ff6f115a0739dac1d64931bffb91Amit Mahajan waitForMs(100); 353153077e0b2d9ff6f115a0739dac1d64931bffb91Amit Mahajan i++; 354153077e0b2d9ff6f115a0739dac1d64931bffb91Amit Mahajan } 355153077e0b2d9ff6f115a0739dac1d64931bffb91Amit Mahajan assertFalse(mGsmInboundSmsHandler.getWakeLock().isHeld()); 35678867803826b15ff95c8ee8c7c6f65dfb7ad258fAmit Mahajan mGsmInboundSmsHandler = null; 35727b650c406018355a88a41528db7859e232728a0Jack Yu super.tearDown(); 35827b650c406018355a88a41528db7859e232728a0Jack Yu } 35927b650c406018355a88a41528db7859e232728a0Jack Yu 36027b650c406018355a88a41528db7859e232728a0Jack Yu private void transitionFromStartupToIdle() { 36127b650c406018355a88a41528db7859e232728a0Jack Yu // verify initially in StartupState 36227b650c406018355a88a41528db7859e232728a0Jack Yu assertEquals("StartupState", getCurrentState().getName()); 36327b650c406018355a88a41528db7859e232728a0Jack Yu 36427b650c406018355a88a41528db7859e232728a0Jack Yu // trigger transition to IdleState 36527b650c406018355a88a41528db7859e232728a0Jack Yu mGsmInboundSmsHandler.sendMessage(InboundSmsHandler.EVENT_START_ACCEPTING_SMS); 36627b650c406018355a88a41528db7859e232728a0Jack Yu waitForMs(50); 36727b650c406018355a88a41528db7859e232728a0Jack Yu 36827b650c406018355a88a41528db7859e232728a0Jack Yu assertEquals("IdleState", getCurrentState().getName()); 36927b650c406018355a88a41528db7859e232728a0Jack Yu } 37027b650c406018355a88a41528db7859e232728a0Jack Yu 37127b650c406018355a88a41528db7859e232728a0Jack Yu private void verifySmsIntentBroadcasts(int numPastBroadcasts) { 37227b650c406018355a88a41528db7859e232728a0Jack Yu ArgumentCaptor<Intent> intentArgumentCaptor = ArgumentCaptor.forClass(Intent.class); 373217d4d9562a9476cf579dfc409b1278a02b18b87Amit Mahajan verify(mContext, times(1 + numPastBroadcasts)).sendBroadcast( 374153077e0b2d9ff6f115a0739dac1d64931bffb91Amit Mahajan intentArgumentCaptor.capture()); 375153077e0b2d9ff6f115a0739dac1d64931bffb91Amit Mahajan assertEquals(Telephony.Sms.Intents.SMS_DELIVER_ACTION, 376153077e0b2d9ff6f115a0739dac1d64931bffb91Amit Mahajan intentArgumentCaptor.getAllValues().get(numPastBroadcasts).getAction()); 377217d4d9562a9476cf579dfc409b1278a02b18b87Amit Mahajan assertEquals("WaitingState", getCurrentState().getName()); 378217d4d9562a9476cf579dfc409b1278a02b18b87Amit Mahajan 379655bae990bdd7e4584491def4d30692e6173779cfionaxu mContextFixture.sendBroadcastToOrderedBroadcastReceivers(); 380655bae990bdd7e4584491def4d30692e6173779cfionaxu 381655bae990bdd7e4584491def4d30692e6173779cfionaxu intentArgumentCaptor = ArgumentCaptor.forClass(Intent.class); 382655bae990bdd7e4584491def4d30692e6173779cfionaxu verify(mContext, times(2 + numPastBroadcasts)).sendBroadcast( 383655bae990bdd7e4584491def4d30692e6173779cfionaxu intentArgumentCaptor.capture()); 384655bae990bdd7e4584491def4d30692e6173779cfionaxu assertEquals(Telephony.Sms.Intents.SMS_RECEIVED_ACTION, 38578867803826b15ff95c8ee8c7c6f65dfb7ad258fAmit Mahajan intentArgumentCaptor.getAllValues().get(numPastBroadcasts + 1).getAction()); 3866ba18ef5f3733709f16ef03b3d2b2de076b63c3efionaxu assertEquals("WaitingState", getCurrentState().getName()); 3876ba18ef5f3733709f16ef03b3d2b2de076b63c3efionaxu 3886ba18ef5f3733709f16ef03b3d2b2de076b63c3efionaxu mContextFixture.sendBroadcastToOrderedBroadcastReceivers(); 3896ba18ef5f3733709f16ef03b3d2b2de076b63c3efionaxu waitForMs(50); 3906ba18ef5f3733709f16ef03b3d2b2de076b63c3efionaxu 3916ba18ef5f3733709f16ef03b3d2b2de076b63c3efionaxu assertEquals("IdleState", getCurrentState().getName()); 3926ba18ef5f3733709f16ef03b3d2b2de076b63c3efionaxu } 39327b650c406018355a88a41528db7859e232728a0Jack Yu 39427b650c406018355a88a41528db7859e232728a0Jack Yu @Test 39527b650c406018355a88a41528db7859e232728a0Jack Yu @MediumTest 396217d4d9562a9476cf579dfc409b1278a02b18b87Amit Mahajan public void testNewSms() { 39775ba09a17a669f4906268088a769836aa87d8241fionaxu transitionFromStartupToIdle(); 39875ba09a17a669f4906268088a769836aa87d8241fionaxu 399217d4d9562a9476cf579dfc409b1278a02b18b87Amit Mahajan // send new SMS to state machine and verify that triggers SMS_DELIVER_ACTION 400f9b150b221db15e88b97a0b9c0971ca3c71c0313fionaxu mGsmInboundSmsHandler.sendMessage(InboundSmsHandler.EVENT_NEW_SMS, 4011bcd7a866ddf8f6f63370c70972f057a4a1ba057Jack Yu new AsyncResult(null, mSmsMessage, null)); 4021bcd7a866ddf8f6f63370c70972f057a4a1ba057Jack Yu waitForMs(100); 4031bcd7a866ddf8f6f63370c70972f057a4a1ba057Jack Yu 4041bcd7a866ddf8f6f63370c70972f057a4a1ba057Jack Yu verifySmsIntentBroadcasts(0); 405ecac744a4e585e3c7af95ffa06fa3e711131200cAmit Mahajan 4067a1c1b02c8603c2bf2f3b401facb389528180eedPavel Zhamaitsiak // send same SMS again, verify no broadcasts are sent 407217d4d9562a9476cf579dfc409b1278a02b18b87Amit Mahajan mGsmInboundSmsHandler.sendMessage(InboundSmsHandler.EVENT_NEW_SMS, 40832b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajan new AsyncResult(null, mSmsMessage, null)); 40932b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajan waitForMs(100); 41032b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajan 411f152b32a20be664788536a223b9ac7a52f69e4ddAmit Mahajan verify(mContext, times(2)).sendBroadcast(any(Intent.class)); 412153077e0b2d9ff6f115a0739dac1d64931bffb91Amit Mahajan assertEquals("IdleState", getCurrentState().getName()); 413153077e0b2d9ff6f115a0739dac1d64931bffb91Amit Mahajan } 414153077e0b2d9ff6f115a0739dac1d64931bffb91Amit Mahajan 4159c96807d990cdd3f4bb2d3f0fd56a1e78a95b353Jack Yu @Test 4169c96807d990cdd3f4bb2d3f0fd56a1e78a95b353Jack Yu @MediumTest 417f152b32a20be664788536a223b9ac7a52f69e4ddAmit Mahajan public void testNewSmsFromBlockedNumber_noBroadcastsSent() { 418f152b32a20be664788536a223b9ac7a52f69e4ddAmit Mahajan String blockedNumber = "123456789"; 41932b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajan doReturn(blockedNumber).when(mInboundSmsTracker).getAddress(); 42032b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajan mFakeBlockedNumberContentProvider.mBlockedNumbers.add(blockedNumber); 42132b5fbb1a340fa16e2c37c276517ef10a4934500Amit Mahajan 422e2435e2d37c991bd6209a90cd884b5102939872eAbhijith Shastry transitionFromStartupToIdle(); 423e2435e2d37c991bd6209a90cd884b5102939872eAbhijith Shastry 424e2435e2d37c991bd6209a90cd884b5102939872eAbhijith Shastry mGsmInboundSmsHandler.sendMessage(InboundSmsHandler.EVENT_NEW_SMS, 4255eccb26b2bcf3a51326596e1b0bb49b073d2f9fcAbhijith Shastry new AsyncResult(null, mSmsMessage, null)); 426e2435e2d37c991bd6209a90cd884b5102939872eAbhijith Shastry waitForMs(100); 427e2435e2d37c991bd6209a90cd884b5102939872eAbhijith Shastry 428e2435e2d37c991bd6209a90cd884b5102939872eAbhijith Shastry verify(mContext, never()).sendBroadcast(any(Intent.class)); 4295eccb26b2bcf3a51326596e1b0bb49b073d2f9fcAbhijith Shastry assertEquals("IdleState", getCurrentState().getName()); 4305eccb26b2bcf3a51326596e1b0bb49b073d2f9fcAbhijith Shastry } 4315eccb26b2bcf3a51326596e1b0bb49b073d2f9fcAbhijith Shastry 4325eccb26b2bcf3a51326596e1b0bb49b073d2f9fcAbhijith Shastry private void verifyDataSmsIntentBroadcasts(int numPastBroadcasts) { 4335eccb26b2bcf3a51326596e1b0bb49b073d2f9fcAbhijith Shastry ArgumentCaptor<Intent> intentArgumentCaptor = ArgumentCaptor.forClass(Intent.class); 4345eccb26b2bcf3a51326596e1b0bb49b073d2f9fcAbhijith Shastry verify(mContext, times(1 + numPastBroadcasts)).sendBroadcast( 4355eccb26b2bcf3a51326596e1b0bb49b073d2f9fcAbhijith Shastry intentArgumentCaptor.capture()); 4365eccb26b2bcf3a51326596e1b0bb49b073d2f9fcAbhijith Shastry assertEquals(Telephony.Sms.Intents.DATA_SMS_RECEIVED_ACTION, 4375eccb26b2bcf3a51326596e1b0bb49b073d2f9fcAbhijith Shastry intentArgumentCaptor.getAllValues().get(numPastBroadcasts).getAction()); 4385eccb26b2bcf3a51326596e1b0bb49b073d2f9fcAbhijith Shastry assertEquals("WaitingState", getCurrentState().getName()); 4395eccb26b2bcf3a51326596e1b0bb49b073d2f9fcAbhijith Shastry 4405eccb26b2bcf3a51326596e1b0bb49b073d2f9fcAbhijith Shastry mContextFixture.sendBroadcastToOrderedBroadcastReceivers(); 4415eccb26b2bcf3a51326596e1b0bb49b073d2f9fcAbhijith Shastry waitForMs(50); 442e2435e2d37c991bd6209a90cd884b5102939872eAbhijith Shastry 443e2435e2d37c991bd6209a90cd884b5102939872eAbhijith Shastry assertEquals("IdleState", getCurrentState().getName()); 4446ba18ef5f3733709f16ef03b3d2b2de076b63c3efionaxu } 4456ba18ef5f3733709f16ef03b3d2b2de076b63c3efionaxu 4466ba18ef5f3733709f16ef03b3d2b2de076b63c3efionaxu @Test 4476ba18ef5f3733709f16ef03b3d2b2de076b63c3efionaxu @MediumTest 4486ba18ef5f3733709f16ef03b3d2b2de076b63c3efionaxu public void testBroadcastSms() { 4496ba18ef5f3733709f16ef03b3d2b2de076b63c3efionaxu transitionFromStartupToIdle(); 45018ad8bf07feb9f6a9d187da236f3e56c055e941afionaxu 451 doReturn(0).when(mInboundSmsTracker).getDestPort(); 452 mGsmInboundSmsHandler.sendMessage(InboundSmsHandler.EVENT_BROADCAST_SMS, 453 mInboundSmsTracker); 454 waitForMs(100); 455 456 verifyDataSmsIntentBroadcasts(0); 457 458 // send same data sms again, and since it's not text sms it should be broadcast again 459 mGsmInboundSmsHandler.sendMessage(InboundSmsHandler.EVENT_BROADCAST_SMS, 460 mInboundSmsTracker); 461 waitForMs(100); 462 463 verifyDataSmsIntentBroadcasts(1); 464 } 465 466 @Test 467 @MediumTest 468 public void testInjectSms() { 469 transitionFromStartupToIdle(); 470 471 mGsmInboundSmsHandler.sendMessage(InboundSmsHandler.EVENT_INJECT_SMS, new AsyncResult(null, 472 mSmsMessage, null)); 473 waitForMs(100); 474 475 verifySmsIntentBroadcasts(0); 476 477 // inject same SMS again, verify no broadcasts are sent 478 mGsmInboundSmsHandler.sendMessage(InboundSmsHandler.EVENT_INJECT_SMS, new AsyncResult(null, 479 mSmsMessage, null)); 480 waitForMs(100); 481 482 verify(mContext, times(2)).sendBroadcast(any(Intent.class)); 483 assertEquals("IdleState", getCurrentState().getName()); 484 } 485 486 private void prepareMultiPartSms() { 487 // Part 1 488 mInboundSmsTrackerCVPart1 = new ContentValues(); 489 mInboundSmsTrackerCVPart1.put("destination_port", 1 << 16); 490 mInboundSmsTrackerCVPart1.put("pdu", HexDump.toHexString(mSmsPdu)); 491 mInboundSmsTrackerCVPart1.put("address", "1234567890"); 492 mInboundSmsTrackerCVPart1.put("reference_number", 1); 493 mInboundSmsTrackerCVPart1.put("sequence", 1); 494 mInboundSmsTrackerCVPart1.put("count", 2); 495 mInboundSmsTrackerCVPart1.put("date", System.currentTimeMillis()); 496 mInboundSmsTrackerCVPart1.put("message_body", mMessageBodyPart1); 497 498 doReturn(2).when(mInboundSmsTrackerPart1).getMessageCount(); 499 doReturn(1).when(mInboundSmsTrackerPart1).getReferenceNumber(); 500 doReturn("1234567890").when(mInboundSmsTrackerPart1).getAddress(); 501 doReturn(1).when(mInboundSmsTrackerPart1).getSequenceNumber(); 502 doReturn(1).when(mInboundSmsTrackerPart1).getIndexOffset(); 503 doReturn(-1).when(mInboundSmsTrackerPart1).getDestPort(); 504 doReturn(mMessageBodyPart1).when(mInboundSmsTrackerPart1).getMessageBody(); 505 doReturn(mSmsPdu).when(mInboundSmsTrackerPart1).getPdu(); 506 doReturn(mInboundSmsTrackerCVPart1.get("date")).when(mInboundSmsTrackerPart1). 507 getTimestamp(); 508 doReturn(mInboundSmsTrackerCVPart1).when(mInboundSmsTrackerPart1).getContentValues(); 509 510 // Part 2 511 mInboundSmsTrackerCVPart2 = new ContentValues(); 512 mInboundSmsTrackerCVPart2.put("destination_port", 1 << 16); 513 mInboundSmsTrackerCVPart2.put("pdu", HexDump.toHexString(mSmsPdu)); 514 mInboundSmsTrackerCVPart2.put("address", "1234567890"); 515 mInboundSmsTrackerCVPart2.put("reference_number", 1); 516 mInboundSmsTrackerCVPart2.put("sequence", 2); 517 mInboundSmsTrackerCVPart2.put("count", 2); 518 mInboundSmsTrackerCVPart2.put("date", System.currentTimeMillis()); 519 mInboundSmsTrackerCVPart2.put("message_body", mMessageBodyPart2); 520 521 doReturn(2).when(mInboundSmsTrackerPart2).getMessageCount(); 522 doReturn(1).when(mInboundSmsTrackerPart2).getReferenceNumber(); 523 doReturn("1234567890").when(mInboundSmsTrackerPart2).getAddress(); 524 doReturn(2).when(mInboundSmsTrackerPart2).getSequenceNumber(); 525 doReturn(1).when(mInboundSmsTrackerPart2).getIndexOffset(); 526 doReturn(-1).when(mInboundSmsTrackerPart2).getDestPort(); 527 doReturn(mMessageBodyPart2).when(mInboundSmsTrackerPart2).getMessageBody(); 528 doReturn(mSmsPdu).when(mInboundSmsTrackerPart2).getPdu(); 529 doReturn(mInboundSmsTrackerCVPart2.get("date")).when(mInboundSmsTrackerPart2). 530 getTimestamp(); 531 doReturn(mInboundSmsTrackerCVPart2).when(mInboundSmsTrackerPart2).getContentValues(); 532 } 533 534 @Test 535 @MediumTest 536 public void testMultiPartSms() { 537 transitionFromStartupToIdle(); 538 539 // prepare SMS part 1 and part 2 540 prepareMultiPartSms(); 541 542 mSmsHeader.concatRef = new SmsHeader.ConcatRef(); 543 doReturn(mSmsHeader).when(mGsmSmsMessage).getUserDataHeader(); 544 545 doReturn(mInboundSmsTrackerPart1).when(mTelephonyComponentFactory) 546 .makeInboundSmsTracker(any(byte[].class), anyLong(), anyInt(), anyBoolean(), 547 anyString(), anyInt(), anyInt(), anyInt(), anyBoolean(), anyString()); 548 mGsmInboundSmsHandler.sendMessage(InboundSmsHandler.EVENT_NEW_SMS, new AsyncResult(null, 549 mSmsMessage, null)); 550 waitForMs(100); 551 552 // State machine should go back to idle and wait for second part 553 assertEquals("IdleState", getCurrentState().getName()); 554 555 doReturn(mInboundSmsTrackerPart2).when(mTelephonyComponentFactory) 556 .makeInboundSmsTracker(any(byte[].class), anyLong(), anyInt(), anyBoolean(), 557 anyString(), anyInt(), anyInt(), anyInt(), anyBoolean(), anyString()); 558 mGsmInboundSmsHandler.sendMessage(InboundSmsHandler.EVENT_NEW_SMS, new AsyncResult(null, 559 mSmsMessage, null)); 560 waitForMs(100); 561 562 // verify broadcast intents 563 verifySmsIntentBroadcasts(0); 564 565 // if an additional copy of one of the segments above is received, it should not be kept in 566 // the db and should not be combined with any subsequent messages received from the same 567 // sender 568 569 // additional copy of part 2 of message 570 doReturn(mInboundSmsTrackerPart2).when(mTelephonyComponentFactory) 571 .makeInboundSmsTracker(any(byte[].class), anyLong(), anyInt(), anyBoolean(), 572 anyString(), anyInt(), anyInt(), anyInt(), anyBoolean(), anyString()); 573 mGsmInboundSmsHandler.sendMessage(InboundSmsHandler.EVENT_NEW_SMS, new AsyncResult(null, 574 mSmsMessage, null)); 575 waitForMs(100); 576 577 // verify no additional broadcasts sent 578 verify(mContext, times(2)).sendBroadcast(any(Intent.class)); 579 580 // part 1 of new sms recieved from same sender with same parameters, just different 581 // timestamps, should not be combined with the additional part 2 received above 582 583 // call prepareMultiPartSms() to update timestamps 584 prepareMultiPartSms(); 585 586 // part 1 of new sms 587 doReturn(mInboundSmsTrackerPart1).when(mTelephonyComponentFactory) 588 .makeInboundSmsTracker(any(byte[].class), anyLong(), anyInt(), anyBoolean(), 589 anyString(), anyInt(), anyInt(), anyInt(), anyBoolean(), anyString()); 590 mGsmInboundSmsHandler.sendMessage(InboundSmsHandler.EVENT_NEW_SMS, new AsyncResult(null, 591 mSmsMessage, null)); 592 waitForMs(100); 593 594 // verify no additional broadcasts sent 595 verify(mContext, times(2)).sendBroadcast(any(Intent.class)); 596 597 assertEquals("IdleState", getCurrentState().getName()); 598 } 599 600 @Test 601 @MediumTest 602 public void testMultiPartIncompleteSms() { 603 /** 604 * Test scenario: 2 messages are received with same address, ref number, count, and 605 * seqNumber, with count = 2 and seqNumber = 1. We should not try to merge these. 606 */ 607 transitionFromStartupToIdle(); 608 609 // prepare SMS part 1 and part 2 610 prepareMultiPartSms(); 611 // change seqNumber in part 2 to 1 612 mInboundSmsTrackerCVPart2.put("sequence", 1); 613 614 mSmsHeader.concatRef = new SmsHeader.ConcatRef(); 615 doReturn(mSmsHeader).when(mGsmSmsMessage).getUserDataHeader(); 616 617 doReturn(mInboundSmsTrackerPart1).when(mTelephonyComponentFactory) 618 .makeInboundSmsTracker(any(byte[].class), anyLong(), anyInt(), anyBoolean(), 619 anyString(), anyInt(), anyInt(), anyInt(), anyBoolean(), anyString()); 620 mGsmInboundSmsHandler.sendMessage(InboundSmsHandler.EVENT_NEW_SMS, new AsyncResult(null, 621 mSmsMessage, null)); 622 waitForMs(100); 623 624 // State machine should go back to idle and wait for second part 625 assertEquals("IdleState", getCurrentState().getName()); 626 627 doReturn(mInboundSmsTrackerPart2).when(mTelephonyComponentFactory) 628 .makeInboundSmsTracker(any(byte[].class), anyLong(), anyInt(), anyBoolean(), 629 anyString(), anyInt(), anyInt(), anyInt(), anyBoolean(), anyString()); 630 mGsmInboundSmsHandler.sendMessage(InboundSmsHandler.EVENT_NEW_SMS, new AsyncResult(null, 631 mSmsMessage, null)); 632 waitForMs(100); 633 634 // verify no broadcasts sent 635 verify(mContext, never()).sendBroadcast(any(Intent.class)); 636 // State machine should go back to idle 637 assertEquals("IdleState", getCurrentState().getName()); 638 } 639 640 @Test 641 @MediumTest 642 public void testMultipartSmsFromBlockedNumber_noBroadcastsSent() { 643 mFakeBlockedNumberContentProvider.mBlockedNumbers.add("1234567890"); 644 645 transitionFromStartupToIdle(); 646 647 // prepare SMS part 1 and part 2 648 prepareMultiPartSms(); 649 650 mSmsHeader.concatRef = new SmsHeader.ConcatRef(); 651 doReturn(mSmsHeader).when(mGsmSmsMessage).getUserDataHeader(); 652 doReturn(mInboundSmsTrackerPart1).when(mTelephonyComponentFactory) 653 .makeInboundSmsTracker(any(byte[].class), anyLong(), anyInt(), anyBoolean(), 654 anyString(), anyInt(), anyInt(), anyInt(), anyBoolean(), anyString()); 655 656 mGsmInboundSmsHandler.sendMessage(InboundSmsHandler.EVENT_NEW_SMS, new AsyncResult(null, 657 mSmsMessage, null)); 658 waitForMs(100); 659 660 // State machine should go back to idle and wait for second part 661 assertEquals("IdleState", getCurrentState().getName()); 662 663 doReturn(mInboundSmsTrackerPart2).when(mTelephonyComponentFactory) 664 .makeInboundSmsTracker(any(byte[].class), anyLong(), anyInt(), anyBoolean(), 665 anyString(), anyInt(), anyInt(), anyInt(), anyBoolean(), anyString()); 666 mGsmInboundSmsHandler.sendMessage(InboundSmsHandler.EVENT_NEW_SMS, new AsyncResult(null, 667 mSmsMessage, null)); 668 waitForMs(100); 669 670 verify(mContext, never()).sendBroadcast(any(Intent.class)); 671 assertEquals("IdleState", getCurrentState().getName()); 672 } 673 674 @Test 675 @MediumTest 676 public void testBroadcastUndeliveredUserLocked() throws Exception { 677 replaceInstance(SmsBroadcastUndelivered.class, "instance", null, null); 678 doReturn(0).when(mInboundSmsTracker).getDestPort(); 679 680 // add a fake entry to db 681 ContentValues rawSms = new ContentValues(); 682 mContentProvider.insert(sRawUri, rawSms); 683 684 // make it a single-part message 685 doReturn(1).when(mInboundSmsTracker).getMessageCount(); 686 687 // user locked 688 UserManager userManager = (UserManager)mContext.getSystemService(Context.USER_SERVICE); 689 doReturn(false).when(userManager).isUserUnlocked(); 690 691 SmsBroadcastUndelivered.initialize(mContext, mGsmInboundSmsHandler, mCdmaInboundSmsHandler); 692 693 // verify that a broadcast receiver is registered for current user (user == null) based on 694 // implementation in ContextFixture 695 verify(mContext).registerReceiverAsUser(any(BroadcastReceiver.class), eq((UserHandle)null), 696 any(IntentFilter.class), eq((String)null), eq((Handler)null)); 697 698 waitForMs(100); 699 700 // verify no broadcasts sent because due to !isUserUnlocked 701 verify(mContext, never()).sendBroadcast(any(Intent.class)); 702 703 // when user unlocks the device, the message in db should be broadcast 704 doReturn(true).when(userManager).isUserUnlocked(); 705 mContext.sendBroadcast(new Intent(Intent.ACTION_USER_UNLOCKED)); 706 waitForMs(100); 707 708 verifyDataSmsIntentBroadcasts(1); 709 } 710 711 @Test 712 @MediumTest 713 public void testBroadcastUndeliveredUserUnlocked() throws Exception { 714 replaceInstance(SmsBroadcastUndelivered.class, "instance", null, null); 715 doReturn(0).when(mInboundSmsTracker).getDestPort(); 716 717 // add a fake entry to db 718 ContentValues rawSms = new ContentValues(); 719 mContentProvider.insert(sRawUri, rawSms); 720 721 // make it a single-part message 722 doReturn(1).when(mInboundSmsTracker).getMessageCount(); 723 724 SmsBroadcastUndelivered.initialize(mContext, mGsmInboundSmsHandler, mCdmaInboundSmsHandler); 725 waitForMs(100); 726 727 // user is unlocked; intent should be broadcast right away 728 verifyDataSmsIntentBroadcasts(0); 729 } 730 731 @Test 732 @MediumTest 733 public void testBroadcastUndeliveredDeleted() throws Exception { 734 replaceInstance(SmsBroadcastUndelivered.class, "instance", null, null); 735 SmsBroadcastUndelivered.initialize(mContext, mGsmInboundSmsHandler, mCdmaInboundSmsHandler); 736 doReturn(0).when(mInboundSmsTracker).getDestPort(); 737 738 //add a fake entry to db 739 ContentValues rawSms = new ContentValues(); 740 rawSms.put("deleted", 1); 741 mContentProvider.insert(sRawUri, rawSms); 742 743 //make it a single-part message 744 doReturn(1).when(mInboundSmsTracker).getMessageCount(); 745 746 //when user unlocks the device, broadcast should not be sent for new message 747 mContext.sendBroadcast(new Intent(Intent.ACTION_USER_UNLOCKED)); 748 waitForMs(100); 749 750 verify(mContext, times(1)).sendBroadcast(any(Intent.class)); 751 assertEquals("IdleState", getCurrentState().getName()); 752 753 } 754 755 @Test 756 @MediumTest 757 public void testBroadcastUndeliveredMultiPart() throws Exception { 758 replaceInstance(SmsBroadcastUndelivered.class, "instance", null, null); 759 760 // prepare SMS part 1 and part 2 761 prepareMultiPartSms(); 762 763 //add the 2 SMS parts to db 764 mContentProvider.insert(sRawUri, mInboundSmsTrackerCVPart1); 765 mContentProvider.insert(sRawUri, mInboundSmsTrackerCVPart2); 766 767 //return InboundSmsTracker objects corresponding to the 2 parts 768 doReturn(mInboundSmsTrackerPart1).doReturn(mInboundSmsTrackerPart2). 769 when(mTelephonyComponentFactory).makeInboundSmsTracker(any(Cursor.class), 770 anyBoolean()); 771 772 SmsBroadcastUndelivered.initialize(mContext, mGsmInboundSmsHandler, mCdmaInboundSmsHandler); 773 waitForMs(100); 774 775 verifySmsIntentBroadcasts(0); 776 } 777} 778