1 /* 2 * Copyright (C) 2019 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.cellbroadcastservice.tests; 18 19 import static com.android.cellbroadcastservice.CellBroadcastProvider.QUERY_COLUMNS; 20 21 import static com.google.common.truth.Truth.assertThat; 22 23 import static org.mockito.Mockito.doReturn; 24 25 import android.content.ContentValues; 26 import android.content.pm.PackageManager; 27 import android.database.Cursor; 28 import android.net.Uri; 29 import android.provider.Telephony.CellBroadcasts; 30 import android.test.mock.MockContentResolver; 31 import android.test.mock.MockContext; 32 import android.util.Log; 33 34 import com.android.cellbroadcastservice.CellBroadcastProvider; 35 import com.android.cellbroadcastservice.CellBroadcastProvider.CellBroadcastPermissionChecker; 36 37 import junit.framework.TestCase; 38 39 import org.junit.Test; 40 import org.mockito.Mock; 41 import org.mockito.MockitoAnnotations; 42 43 public class CellBroadcastProviderTest extends TestCase { 44 private static final String TAG = CellBroadcastProviderTest.class.getSimpleName(); 45 46 public static final Uri CONTENT_URI = Uri.parse("content://cellbroadcasts"); 47 48 private static final int GEO_SCOPE = 1; 49 private static final String PLMN = "123456"; 50 private static final int LAC = 13; 51 private static final int CID = 123; 52 private static final int SERIAL_NUMBER = 17984; 53 private static final int SERVICE_CATEGORY = 4379; 54 private static final String LANGUAGE_CODE = "en"; 55 private static final String MESSAGE_BODY = "AMBER Alert: xxxx"; 56 private static final int MESSAGE_FORMAT = 1; 57 private static final int MESSAGE_PRIORITY = 3; 58 private static final int ETWS_WARNING_TYPE = 1; 59 private static final int ETWS_IS_PRIMARY = 0; 60 private static final int CMAS_MESSAGE_CLASS = 1; 61 private static final int CMAS_CATEGORY = 6; 62 private static final int CMAS_RESPONSE_TYPE = 1; 63 private static final int CMAS_SEVERITY = 2; 64 private static final int CMAS_URGENCY = 3; 65 private static final int CMAS_CERTAINTY = 4; 66 private static final int RECEIVED_TIME = 1562792637; 67 private static final int MESSAGE_BROADCASTED = 1; 68 private static final int MESSAGE_NOT_DISPLAYED = 0; 69 private static final String GEOMETRIES_COORDINATES = "polygon|0,0|0,1|1,1|1,0;circle|0,0|100"; 70 71 private static final String SELECT_BY_ID = CellBroadcasts._ID + "=?"; 72 73 private CellBroadcastProviderTestable mCellBroadcastProviderTestable; 74 private MockContextWithProvider mContext; 75 private MockContentResolver mContentResolver; 76 77 @Mock 78 private CellBroadcastPermissionChecker mMockPermissionChecker; 79 80 @Override setUp()81 protected void setUp() throws Exception { 82 super.setUp(); 83 MockitoAnnotations.initMocks(this); 84 doReturn(true).when(mMockPermissionChecker).hasFullAccessPermission(); 85 86 mCellBroadcastProviderTestable = new CellBroadcastProviderTestable(mMockPermissionChecker); 87 mContext = new MockContextWithProvider(mCellBroadcastProviderTestable); 88 mContentResolver = mContext.getContentResolver(); 89 } 90 91 @Override tearDown()92 protected void tearDown() throws Exception { 93 mCellBroadcastProviderTestable.closeDatabase(); 94 super.tearDown(); 95 } 96 97 @Test testUpdate()98 public void testUpdate() { 99 // Insert a cellbroadcast to the database. 100 ContentValues cv = fakeCellBroadcast(); 101 Uri uri = mContentResolver.insert(CONTENT_URI, cv); 102 assertThat(uri).isNotNull(); 103 104 // Change some fields of this cell broadcast. 105 int messageDisplayed = 1 - cv.getAsInteger(CellBroadcasts.MESSAGE_DISPLAYED); 106 int receivedTime = 1234555555; 107 cv.put(CellBroadcasts.MESSAGE_DISPLAYED, messageDisplayed); 108 cv.put(CellBroadcasts.RECEIVED_TIME, receivedTime); 109 mContentResolver.update(CONTENT_URI, cv, SELECT_BY_ID, 110 new String[] { uri.getLastPathSegment() }); 111 112 // Query and check if the update is succeeded. 113 Cursor cursor = mContentResolver.query(CONTENT_URI, QUERY_COLUMNS, 114 SELECT_BY_ID, new String[] { uri.getLastPathSegment() }, null /* orderBy */); 115 cursor.moveToNext(); 116 117 assertThat(cursor.getInt(cursor.getColumnIndexOrThrow(CellBroadcasts.RECEIVED_TIME))) 118 .isEqualTo(receivedTime); 119 assertThat(cursor.getInt(cursor.getColumnIndexOrThrow(CellBroadcasts.MESSAGE_DISPLAYED))) 120 .isEqualTo(messageDisplayed); 121 cursor.close(); 122 } 123 124 @Test testUpdate_WithoutWritePermission_fail()125 public void testUpdate_WithoutWritePermission_fail() { 126 ContentValues cv = fakeCellBroadcast(); 127 Uri uri = mContentResolver.insert(CONTENT_URI, cv); 128 assertThat(uri).isNotNull(); 129 130 // Revoke the write permission 131 doReturn(false).when(mMockPermissionChecker).hasFullAccessPermission(); 132 133 try { 134 mContentResolver.update(CONTENT_URI, cv, SELECT_BY_ID, 135 new String[] { uri.getLastPathSegment() }); 136 fail(); 137 } catch (SecurityException ex) { 138 // pass the test 139 } 140 } 141 142 @Test testGetAllCellBroadcast()143 public void testGetAllCellBroadcast() { 144 // Insert some cell broadcasts which message_displayed is false 145 int messageNotDisplayedCount = 5; 146 ContentValues cv = fakeCellBroadcast(); 147 cv.put(CellBroadcasts.MESSAGE_DISPLAYED, 0); 148 for (int i = 0; i < messageNotDisplayedCount; i++) { 149 mContentResolver.insert(CONTENT_URI, cv); 150 } 151 152 // Insert some cell broadcasts which message_displayed is true 153 int messageDisplayedCount = 6; 154 cv.put(CellBroadcasts.MESSAGE_DISPLAYED, 1); 155 for (int i = 0; i < messageDisplayedCount; i++) { 156 mContentResolver.insert(CONTENT_URI, cv); 157 } 158 159 // Query the broadcast with message_displayed is false 160 Cursor cursor = mContentResolver.query( 161 CONTENT_URI, 162 QUERY_COLUMNS, 163 String.format("%s=?", CellBroadcasts.MESSAGE_DISPLAYED), /* selection */ 164 new String[] {"0"}, /* selectionArgs */ 165 null /* sortOrder */); 166 assertThat(cursor.getCount()).isEqualTo(messageNotDisplayedCount); 167 } 168 169 @Test testDelete_withoutWritePermission_throwSecurityException()170 public void testDelete_withoutWritePermission_throwSecurityException() { 171 Uri uri = mContentResolver.insert(CONTENT_URI, fakeCellBroadcast()); 172 assertThat(uri).isNotNull(); 173 174 // Revoke the write permission 175 doReturn(false).when(mMockPermissionChecker).hasFullAccessPermission(); 176 177 try { 178 mContentResolver.delete(CONTENT_URI, SELECT_BY_ID, 179 new String[] { uri.getLastPathSegment() }); 180 fail(); 181 } catch (SecurityException ex) { 182 // pass the test 183 } 184 } 185 186 187 @Test testDelete_oneRecord_success()188 public void testDelete_oneRecord_success() { 189 // Insert a cellbroadcast to the database. 190 ContentValues cv = fakeCellBroadcast(); 191 Uri uri = mContentResolver.insert(CONTENT_URI, cv); 192 assertThat(uri).isNotNull(); 193 194 String[] selectionArgs = new String[] { uri.getLastPathSegment() }; 195 196 // Ensure the cell broadcast is inserted. 197 Cursor cursor = mContentResolver.query(CONTENT_URI, QUERY_COLUMNS, 198 SELECT_BY_ID, selectionArgs, null /* orderBy */); 199 assertThat(cursor.getCount()).isEqualTo(1); 200 cursor.close(); 201 202 // Delete the cell broadcast 203 int rowCount = mContentResolver.delete(CONTENT_URI, SELECT_BY_ID, 204 selectionArgs); 205 assertThat(rowCount).isEqualTo(1); 206 207 // Ensure the cell broadcast is deleted. 208 cursor = mContentResolver.query(CONTENT_URI, QUERY_COLUMNS, SELECT_BY_ID, 209 selectionArgs, null /* orderBy */); 210 assertThat(cursor.getCount()).isEqualTo(0); 211 cursor.close(); 212 } 213 214 @Test testDelete_all_success()215 public void testDelete_all_success() { 216 // Insert a cellbroadcast to the database. 217 mContentResolver.insert(CONTENT_URI, fakeCellBroadcast()); 218 mContentResolver.insert(CONTENT_URI, fakeCellBroadcast()); 219 220 // Ensure the cell broadcast are inserted. 221 Cursor cursor = mContentResolver.query(CONTENT_URI, QUERY_COLUMNS, 222 null /* selection */, null /* selectionArgs */, null /* orderBy */); 223 assertThat(cursor.getCount()).isEqualTo(2); 224 cursor.close(); 225 226 // Delete all cell broadcasts. 227 int rowCount = mContentResolver.delete( 228 CONTENT_URI, null /* selection */, null /* selectionArgs */); 229 assertThat(rowCount).isEqualTo(2); 230 cursor.close(); 231 232 // Ensure all cell broadcasts are deleted. 233 cursor = mContentResolver.query(CONTENT_URI, QUERY_COLUMNS, 234 null /* selection */, null /* selectionArgs */, null /* orderBy */); 235 assertThat(cursor.getCount()).isEqualTo(0); 236 cursor.close(); 237 } 238 239 @Test testInsert_withoutWritePermission_fail()240 public void testInsert_withoutWritePermission_fail() { 241 doReturn(false).when(mMockPermissionChecker).hasFullAccessPermission(); 242 243 try { 244 mContentResolver.insert(CONTENT_URI, fakeCellBroadcast()); 245 fail(); 246 } catch (SecurityException ex) { 247 // pass the test 248 } 249 } 250 251 @Test testInsertAndQuery()252 public void testInsertAndQuery() { 253 // Insert a cell broadcast message 254 Uri uri = mContentResolver.insert(CONTENT_URI, fakeCellBroadcast()); 255 256 // Verify that the return uri is not null and the record is inserted into the database 257 // correctly. 258 assertThat(uri).isNotNull(); 259 Cursor cursor = mContentResolver.query( 260 CONTENT_URI, QUERY_COLUMNS, SELECT_BY_ID, 261 new String[] { uri.getLastPathSegment() }, null /* orderBy */); 262 assertThat(cursor.getCount()).isEqualTo(1); 263 264 cursor.moveToNext(); 265 assertThat(cursor.getInt(cursor.getColumnIndexOrThrow(CellBroadcasts.GEOGRAPHICAL_SCOPE))) 266 .isEqualTo(GEO_SCOPE); 267 assertThat(cursor.getString(cursor.getColumnIndexOrThrow(CellBroadcasts.PLMN))) 268 .isEqualTo(PLMN); 269 assertThat(cursor.getInt(cursor.getColumnIndexOrThrow(CellBroadcasts.LAC))).isEqualTo(LAC); 270 assertThat(cursor.getInt(cursor.getColumnIndexOrThrow(CellBroadcasts.CID))).isEqualTo(CID); 271 assertThat(cursor.getInt(cursor.getColumnIndexOrThrow(CellBroadcasts.SERIAL_NUMBER))) 272 .isEqualTo(SERIAL_NUMBER); 273 assertThat(cursor.getInt(cursor.getColumnIndexOrThrow(CellBroadcasts.SERVICE_CATEGORY))) 274 .isEqualTo(SERVICE_CATEGORY); 275 assertThat(cursor.getString(cursor.getColumnIndexOrThrow(CellBroadcasts.LANGUAGE_CODE))) 276 .isEqualTo(LANGUAGE_CODE); 277 assertThat(cursor.getString(cursor.getColumnIndexOrThrow(CellBroadcasts.MESSAGE_BODY))) 278 .isEqualTo(MESSAGE_BODY); 279 assertThat(cursor.getInt(cursor.getColumnIndexOrThrow(CellBroadcasts.MESSAGE_FORMAT))) 280 .isEqualTo(MESSAGE_FORMAT); 281 assertThat(cursor.getInt(cursor.getColumnIndexOrThrow(CellBroadcasts.MESSAGE_PRIORITY))) 282 .isEqualTo(MESSAGE_PRIORITY); 283 assertThat(cursor.getInt(cursor.getColumnIndexOrThrow(CellBroadcasts.ETWS_WARNING_TYPE))) 284 .isEqualTo(ETWS_WARNING_TYPE); 285 assertThat(cursor.getInt(cursor.getColumnIndexOrThrow(CellBroadcasts.ETWS_IS_PRIMARY))) 286 .isEqualTo(ETWS_IS_PRIMARY); 287 assertThat(cursor.getInt(cursor.getColumnIndexOrThrow(CellBroadcasts.CMAS_MESSAGE_CLASS))) 288 .isEqualTo(CMAS_MESSAGE_CLASS); 289 assertThat(cursor.getInt(cursor.getColumnIndexOrThrow(CellBroadcasts.CMAS_CATEGORY))) 290 .isEqualTo(CMAS_CATEGORY); 291 assertThat(cursor.getInt(cursor.getColumnIndexOrThrow(CellBroadcasts.CMAS_RESPONSE_TYPE))) 292 .isEqualTo(CMAS_RESPONSE_TYPE); 293 assertThat(cursor.getInt(cursor.getColumnIndexOrThrow(CellBroadcasts.CMAS_SEVERITY))) 294 .isEqualTo(CMAS_SEVERITY); 295 assertThat(cursor.getInt(cursor.getColumnIndexOrThrow(CellBroadcasts.CMAS_URGENCY))) 296 .isEqualTo(CMAS_URGENCY); 297 assertThat(cursor.getInt(cursor.getColumnIndexOrThrow(CellBroadcasts.CMAS_CERTAINTY))) 298 .isEqualTo(CMAS_CERTAINTY); 299 assertThat(cursor.getInt(cursor.getColumnIndexOrThrow(CellBroadcasts.RECEIVED_TIME))) 300 .isEqualTo(RECEIVED_TIME); 301 assertThat(cursor.getInt(cursor.getColumnIndexOrThrow(CellBroadcasts.MESSAGE_BROADCASTED))) 302 .isEqualTo(MESSAGE_BROADCASTED); 303 assertThat(cursor.getInt(cursor.getColumnIndexOrThrow(CellBroadcasts.MESSAGE_DISPLAYED))) 304 .isEqualTo(MESSAGE_NOT_DISPLAYED); 305 assertThat(cursor.getString(cursor.getColumnIndexOrThrow( 306 CellBroadcasts.GEOMETRIES))).isEqualTo(GEOMETRIES_COORDINATES); 307 } 308 309 /** 310 * This is used to give the CellBroadcastProviderTest a mocked context which takes a 311 * CellBroadcastProvider and attaches it to the ContentResolver. 312 */ 313 private class MockContextWithProvider extends MockContext { 314 private final MockContentResolver mResolver; 315 MockContextWithProvider(CellBroadcastProviderTestable cellBroadcastProvider)316 MockContextWithProvider(CellBroadcastProviderTestable cellBroadcastProvider) { 317 mResolver = new MockContentResolver(); 318 cellBroadcastProvider.initializeForTesting(this); 319 320 // Add given cellBroadcastProvider to mResolver, so that mResolver can send queries 321 // to the provider. 322 mResolver.addProvider(CellBroadcastProvider.AUTHORITY, cellBroadcastProvider); 323 } 324 325 @Override getContentResolver()326 public MockContentResolver getContentResolver() { 327 return mResolver; 328 } 329 330 331 @Override getSystemService(String name)332 public Object getSystemService(String name) { 333 Log.d(TAG, "getSystemService: returning null"); 334 return null; 335 } 336 337 @Override checkCallingOrSelfPermission(String permission)338 public int checkCallingOrSelfPermission(String permission) { 339 return PackageManager.PERMISSION_GRANTED; 340 } 341 } 342 fakeCellBroadcast()343 private static ContentValues fakeCellBroadcast() { 344 ContentValues cv = new ContentValues(); 345 cv.put(CellBroadcasts.GEOGRAPHICAL_SCOPE, GEO_SCOPE); 346 cv.put(CellBroadcasts.PLMN, PLMN); 347 cv.put(CellBroadcasts.LAC, LAC); 348 cv.put(CellBroadcasts.CID, CID); 349 cv.put(CellBroadcasts.SERIAL_NUMBER, SERIAL_NUMBER); 350 cv.put(CellBroadcasts.SERVICE_CATEGORY, SERVICE_CATEGORY); 351 cv.put(CellBroadcasts.LANGUAGE_CODE, LANGUAGE_CODE); 352 cv.put(CellBroadcasts.MESSAGE_BODY, MESSAGE_BODY); 353 cv.put(CellBroadcasts.MESSAGE_FORMAT, MESSAGE_FORMAT); 354 cv.put(CellBroadcasts.MESSAGE_PRIORITY, MESSAGE_PRIORITY); 355 cv.put(CellBroadcasts.ETWS_WARNING_TYPE, ETWS_WARNING_TYPE); 356 cv.put(CellBroadcasts.ETWS_IS_PRIMARY, ETWS_IS_PRIMARY); 357 cv.put(CellBroadcasts.CMAS_MESSAGE_CLASS, CMAS_MESSAGE_CLASS); 358 cv.put(CellBroadcasts.CMAS_CATEGORY, CMAS_CATEGORY); 359 cv.put(CellBroadcasts.CMAS_RESPONSE_TYPE, CMAS_RESPONSE_TYPE); 360 cv.put(CellBroadcasts.CMAS_SEVERITY, CMAS_SEVERITY); 361 cv.put(CellBroadcasts.CMAS_URGENCY, CMAS_URGENCY); 362 cv.put(CellBroadcasts.CMAS_CERTAINTY, CMAS_CERTAINTY); 363 cv.put(CellBroadcasts.RECEIVED_TIME, RECEIVED_TIME); 364 cv.put(CellBroadcasts.MESSAGE_BROADCASTED, MESSAGE_BROADCASTED); 365 cv.put(CellBroadcasts.MESSAGE_DISPLAYED, MESSAGE_NOT_DISPLAYED); 366 cv.put(CellBroadcasts.GEOMETRIES, GEOMETRIES_COORDINATES); 367 return cv; 368 } 369 } 370