1 /* 2 * Copyright (C) 2020 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 package com.android.cellbroadcastreceiver.unit; 17 18 import static org.mockito.ArgumentMatchers.any; 19 import static org.mockito.Mockito.doReturn; 20 import static com.google.common.truth.Truth.assertThat; 21 import static org.mockito.Mockito.times; 22 import static org.mockito.Mockito.verify; 23 24 import android.content.ContentProvider; 25 import android.content.ContentValues; 26 import android.content.Context; 27 import android.content.pm.PackageManager; 28 import android.content.res.Configuration; 29 import android.content.res.Resources; 30 import android.database.Cursor; 31 import android.net.Uri; 32 import android.os.UserManager; 33 import android.provider.Telephony.CellBroadcasts; 34 import android.telephony.SmsCbCmasInfo; 35 import android.telephony.SmsCbEtwsInfo; 36 import android.telephony.SmsCbLocation; 37 import android.telephony.SmsCbMessage; 38 import android.telephony.SubscriptionManager; 39 import android.test.mock.MockContentResolver; 40 import android.test.mock.MockContext; 41 import android.util.Log; 42 import com.android.cellbroadcastreceiver.CellBroadcastDatabaseHelper; 43 import junit.framework.TestCase; 44 import org.junit.Test; 45 import org.mockito.Mock; 46 import org.mockito.MockitoAnnotations; 47 48 public class CellBroadcastContentProviderTest extends TestCase { 49 private static final String TAG = CellBroadcastContentProviderTest.class.getSimpleName(); 50 51 public static final Uri CONTENT_URI = Uri.parse("content://cellbroadcasts-app"); 52 53 private static final int GEO_SCOPE = 1; 54 private static final String PLMN = "123456"; 55 private static final int LAC = 13; 56 private static final int CID = 123; 57 private static final int SERIAL_NUMBER = 17984; 58 private static final int SERVICE_CATEGORY = 4379; 59 private static final String LANGUAGE_CODE = "en"; 60 private static final String MESSAGE_BODY = "AMBER Alert: xxxx"; 61 private static final int MESSAGE_FORMAT = 1; 62 private static final int MESSAGE_PRIORITY = 3; 63 private static final int ETWS_WARNING_TYPE = 1; 64 private static final int CMAS_MESSAGE_CLASS = 1; 65 private static final int CMAS_CATEGORY = 6; 66 private static final int CMAS_RESPONSE_TYPE = 1; 67 private static final int CMAS_SEVERITY = 2; 68 private static final int CMAS_URGENCY = 3; 69 private static final int CMAS_CERTAINTY = 4; 70 71 private CellBroadcastContentProviderTestable mCellBroadcastProviderTestable; 72 private MockContextWithProvider mContext; 73 private MockContentResolver mContentResolver; 74 @Mock 75 UserManager mUserManager; 76 @Mock 77 SubscriptionManager mSubManager; 78 @Mock 79 ContentProvider mMockSmsProvider; 80 @Mock 81 Resources mMockResource; 82 @Mock 83 Context mMockContext; 84 85 @Override setUp()86 protected void setUp() throws Exception { 87 super.setUp(); 88 MockitoAnnotations.initMocks(this); 89 90 mCellBroadcastProviderTestable = new CellBroadcastContentProviderTestable(); 91 mContext = new MockContextWithProvider(mCellBroadcastProviderTestable); 92 mContentResolver = mContext.getContentResolver(); 93 } 94 95 @Override tearDown()96 protected void tearDown() throws Exception { 97 mCellBroadcastProviderTestable.closeDatabase(); 98 super.tearDown(); 99 } 100 101 @Test 102 @InstrumentationTest 103 // This test requires the content provider from the cell broadcast module, so it is disabled for 104 // OEM testing because it is not a true unit test testInsert()105 public void testInsert() { 106 try { 107 ContentValues msg = new ContentValues(); 108 msg.put(CellBroadcasts.SERIAL_NUMBER, SERIAL_NUMBER); 109 mContentResolver.insert(CONTENT_URI, msg); 110 fail(); 111 } catch (UnsupportedOperationException ex) { 112 // pass the test 113 } 114 } 115 116 @Test 117 @InstrumentationTest 118 // This test requires the content provider from the cell broadcast module, so it is disabled for 119 // OEM testing because it is not a true unit test testDelete()120 public void testDelete() { 121 try { 122 mContentResolver.delete(CONTENT_URI, null, null); 123 fail(); 124 } catch (UnsupportedOperationException ex) { 125 // pass the test 126 } 127 } 128 129 @Test 130 @InstrumentationTest 131 // This test requires the content provider from the cell broadcast module, so it is disabled for 132 // OEM testing because it is not a true unit test testUpdate()133 public void testUpdate() { 134 try { 135 mContentResolver.update(CONTENT_URI, null, null); 136 fail(); 137 } catch (UnsupportedOperationException ex) { 138 // pass the test 139 } 140 } 141 142 @Test 143 @InstrumentationTest 144 // This test requires the content provider from the cell broadcast module, so it is disabled for 145 // OEM testing because it is not a true unit test testDeleteAll()146 public void testDeleteAll() { 147 // Insert a cell broadcast message 148 mCellBroadcastProviderTestable.insertNewBroadcast(fakeSmsCbMessage()); 149 // Verify that the record is inserted into the database correctly. 150 Cursor cursor = mContentResolver.query(CONTENT_URI, 151 CellBroadcastDatabaseHelper.QUERY_COLUMNS, null, null, null); 152 assertThat(cursor.getCount()).isEqualTo(1); 153 // delete all 154 mCellBroadcastProviderTestable.deleteAllBroadcasts(); 155 cursor = mContentResolver.query(CONTENT_URI, CellBroadcastDatabaseHelper.QUERY_COLUMNS, 156 null, null, null); 157 assertThat(cursor.getCount()).isEqualTo(0); 158 } 159 160 @Test 161 @InstrumentationTest 162 // This test requires the content provider from the cell broadcast module, so it is disabled for 163 // OEM testing because it is not a true unit test testDeleteBroadcast()164 public void testDeleteBroadcast() { 165 // Insert two cell broadcast message 166 mCellBroadcastProviderTestable.insertNewBroadcast(fakeSmsCbMessage()); 167 mCellBroadcastProviderTestable.insertNewBroadcast(fakeSmsCbMessage()); 168 // Verify that the record is inserted into the database correctly. 169 Cursor cursor = mContentResolver.query(CONTENT_URI, 170 CellBroadcastDatabaseHelper.QUERY_COLUMNS, null, null, null); 171 assertThat(cursor.getCount()).isEqualTo(2); 172 // delete one message 173 mCellBroadcastProviderTestable.deleteBroadcast(1); 174 cursor = mContentResolver.query(CONTENT_URI, CellBroadcastDatabaseHelper.QUERY_COLUMNS, 175 null, null, null); 176 assertThat(cursor.getCount()).isEqualTo(1); 177 } 178 179 @Test 180 @InstrumentationTest testMarkSmsSyncPending()181 public void testMarkSmsSyncPending() { 182 SmsCbMessage msg = fakeSmsCbMessage(); 183 long deliveryTime = msg.getReceivedTime(); 184 mCellBroadcastProviderTestable.insertNewBroadcast(msg); 185 // Verify that there is no record with smsSyncPending set 186 Cursor cursor = mContentResolver.query(CONTENT_URI, 187 CellBroadcastDatabaseHelper.QUERY_COLUMNS, 188 CellBroadcastDatabaseHelper.SMS_SYNC_PENDING + "=1" , null, null); 189 assertThat(cursor.getCount()).isEqualTo(0); 190 mCellBroadcastProviderTestable.markBroadcastSmsSyncPending( 191 CellBroadcasts.DELIVERY_TIME, 192 deliveryTime, true); 193 cursor = mContentResolver.query(CONTENT_URI, 194 CellBroadcastDatabaseHelper.QUERY_COLUMNS, 195 CellBroadcastDatabaseHelper.SMS_SYNC_PENDING + "=1" , null, null); 196 assertThat(cursor.getCount()).isEqualTo(1); 197 } 198 199 @Test 200 @InstrumentationTest testWriteSmsInboxBeforeUserUnlock()201 public void testWriteSmsInboxBeforeUserUnlock() { 202 doReturn(false).when(mUserManager).isUserUnlocked(); 203 doReturn(true).when(mUserManager).isSystemUser(); 204 SmsCbMessage msg = fakeSmsCbMessage(); 205 mCellBroadcastProviderTestable.insertNewBroadcast(msg); 206 // verify does not write message to SMS db 207 mCellBroadcastProviderTestable.writeMessageToSmsInbox(msg, mContext); 208 // Verify that there is a record with smsSyncPending set 209 Cursor cursor = mContentResolver.query(CONTENT_URI, 210 CellBroadcastDatabaseHelper.QUERY_COLUMNS, 211 CellBroadcastDatabaseHelper.SMS_SYNC_PENDING + "=1" , null, null); 212 assertThat(cursor.getCount()).isEqualTo(1); 213 verify(mMockSmsProvider, times(0)).insert(any(), any()); 214 } 215 216 @Test 217 @InstrumentationTest testWriteSmsInboxNonSystemUser()218 public void testWriteSmsInboxNonSystemUser() { 219 doReturn(false).when(mUserManager).isSystemUser(); 220 SmsCbMessage msg = fakeSmsCbMessage(); 221 // verify does not write message to SMS db 222 mCellBroadcastProviderTestable.writeMessageToSmsInbox(msg, mContext); 223 verify(mMockSmsProvider, times(0)).insert(any(), any()); 224 } 225 226 @Test 227 @InstrumentationTest 228 // This test requires the content provider from the cell broadcast module, so it is disabled for 229 // OEM testing because it is not a true unit test testInsertQuery()230 public void testInsertQuery() { 231 // Insert a cell broadcast message 232 mCellBroadcastProviderTestable.insertNewBroadcast(fakeSmsCbMessage()); 233 234 // Verify that the record is inserted into the database correctly. 235 Cursor cursor = mContentResolver.query(CONTENT_URI, 236 CellBroadcastDatabaseHelper.QUERY_COLUMNS, null, null, null); 237 assertThat(cursor.getCount()).isEqualTo(1); 238 239 cursor.moveToNext(); 240 assertThat(cursor.getInt(cursor.getColumnIndexOrThrow(CellBroadcasts.GEOGRAPHICAL_SCOPE))) 241 .isEqualTo(GEO_SCOPE); 242 assertThat(cursor.getString(cursor.getColumnIndexOrThrow(CellBroadcasts.PLMN))) 243 .isEqualTo(PLMN); 244 assertThat(cursor.getInt(cursor.getColumnIndexOrThrow(CellBroadcasts.LAC))).isEqualTo(LAC); 245 assertThat(cursor.getInt(cursor.getColumnIndexOrThrow(CellBroadcasts.CID))).isEqualTo(CID); 246 assertThat(cursor.getInt(cursor.getColumnIndexOrThrow(CellBroadcasts.SERIAL_NUMBER))) 247 .isEqualTo(SERIAL_NUMBER); 248 assertThat(cursor.getInt(cursor.getColumnIndexOrThrow(CellBroadcasts.SERVICE_CATEGORY))) 249 .isEqualTo(SERVICE_CATEGORY); 250 assertThat(cursor.getString(cursor.getColumnIndexOrThrow(CellBroadcasts.LANGUAGE_CODE))) 251 .isEqualTo(LANGUAGE_CODE); 252 assertThat(cursor.getString(cursor.getColumnIndexOrThrow(CellBroadcasts.MESSAGE_BODY))) 253 .isEqualTo(MESSAGE_BODY); 254 assertThat(cursor.getInt(cursor.getColumnIndexOrThrow(CellBroadcasts.MESSAGE_PRIORITY))) 255 .isEqualTo(MESSAGE_PRIORITY); 256 assertThat(cursor.getInt(cursor.getColumnIndexOrThrow(CellBroadcasts.ETWS_WARNING_TYPE))) 257 .isEqualTo(ETWS_WARNING_TYPE); 258 assertThat(cursor.getInt(cursor.getColumnIndexOrThrow(CellBroadcasts.CMAS_MESSAGE_CLASS))) 259 .isEqualTo(CMAS_MESSAGE_CLASS); 260 assertThat(cursor.getInt(cursor.getColumnIndexOrThrow(CellBroadcasts.CMAS_CATEGORY))) 261 .isEqualTo(CMAS_CATEGORY); 262 assertThat(cursor.getInt(cursor.getColumnIndexOrThrow(CellBroadcasts.CMAS_RESPONSE_TYPE))) 263 .isEqualTo(CMAS_RESPONSE_TYPE); 264 assertThat(cursor.getInt(cursor.getColumnIndexOrThrow(CellBroadcasts.CMAS_SEVERITY))) 265 .isEqualTo(CMAS_SEVERITY); 266 assertThat(cursor.getInt(cursor.getColumnIndexOrThrow(CellBroadcasts.CMAS_URGENCY))) 267 .isEqualTo(CMAS_URGENCY); 268 assertThat(cursor.getInt(cursor.getColumnIndexOrThrow(CellBroadcasts.CMAS_CERTAINTY))) 269 .isEqualTo(CMAS_CERTAINTY); 270 } 271 272 /** 273 * This is used to give the CellBroadcastContentProviderTest a mocked context which takes a 274 * CellBroadcastProvider and attaches it to the ContentResolver. 275 */ 276 private class MockContextWithProvider extends MockContext { 277 private final MockContentResolver mResolver; 278 MockContextWithProvider(CellBroadcastContentProviderTestable cellBroadcastProvider)279 MockContextWithProvider(CellBroadcastContentProviderTestable cellBroadcastProvider) { 280 mResolver = new MockContentResolver(); 281 cellBroadcastProvider.initializeForTesting(this); 282 283 // Add given cellBroadcastProvider to mResolver, so that mResolver can send queries 284 // to the provider. 285 mResolver.addProvider("cellbroadcasts-app", cellBroadcastProvider); 286 } 287 288 @Override getResources()289 public Resources getResources() { 290 return mMockResource; 291 } 292 293 @Override createConfigurationContext(Configuration overrideConfiguration)294 public Context createConfigurationContext(Configuration overrideConfiguration) { 295 return mMockContext; 296 } 297 298 @Override getContentResolver()299 public MockContentResolver getContentResolver() { 300 return mResolver; 301 } 302 303 304 @Override getSystemService(String name)305 public Object getSystemService(String name) { 306 switch(name) { 307 case Context.USER_SERVICE: 308 return mUserManager; 309 case Context.TELEPHONY_SUBSCRIPTION_SERVICE: 310 return mSubManager; 311 default: 312 Log.d(TAG, "getSystemService: returning null"); 313 return null; 314 } 315 } 316 317 @Override checkCallingOrSelfPermission(String permission)318 public int checkCallingOrSelfPermission(String permission) { 319 return PackageManager.PERMISSION_GRANTED; 320 } 321 } 322 fakeSmsCbMessage()323 private SmsCbMessage fakeSmsCbMessage() { 324 return new SmsCbMessage(MESSAGE_FORMAT, GEO_SCOPE, SERIAL_NUMBER, 325 new SmsCbLocation(PLMN, LAC, CID), SERVICE_CATEGORY, LANGUAGE_CODE, 0 , 326 MESSAGE_BODY, MESSAGE_PRIORITY, new SmsCbEtwsInfo(ETWS_WARNING_TYPE, false, 327 false, false, null), 328 new SmsCbCmasInfo(CMAS_MESSAGE_CLASS, CMAS_CATEGORY, CMAS_RESPONSE_TYPE, 329 CMAS_SEVERITY, CMAS_URGENCY, CMAS_CERTAINTY), 0, null, 330 System.currentTimeMillis(), 1, SubscriptionManager.INVALID_SUBSCRIPTION_ID); 331 } 332 } 333