Loading android/app/src/com/android/bluetooth/mapclient/MapClientContent.java +25 −6 Original line number Diff line number Diff line Loading @@ -269,6 +269,11 @@ class MapClientContent { values.put(Sms.SEEN, seen); Uri results = mResolver.insert(contentUri, values); if (results == null) { error("Failed to get SMS URI, insert failed. Dropping message."); return; } mHandleToUriMap.put(handle, results); mUriToHandleMap.put(results, new MessageStatus(handle, readStatus)); debug("Map InsertedThread" + results); Loading Loading @@ -375,6 +380,11 @@ class MapClientContent { values.put(Mms.MESSAGE_SIZE, mmsBmessage.getSize()); Uri results = mResolver.insert(contentUri, values); if (results == null) { error("Failed to get MMS entry URI. Cannot store MMS parts. Dropping message."); return; } mHandleToUriMap.put(handle, results); mUriToHandleMap.put(results, new MessageStatus(handle, read)); Loading @@ -385,9 +395,6 @@ class MapClientContent { } storeAddressPart(message, results); values.put(Mms.Part.CONTENT_TYPE, "plain/text"); values.put(Mms.SUBSCRIPTION_ID, mSubscriptionId); } catch (Exception e) { error("Error while storing MMS: " + e.toString()); throw e; Loading @@ -406,6 +413,12 @@ class MapClientContent { Uri contentUri = Uri.parse(messageUri.toString() + "/part"); Uri results = mResolver.insert(contentUri, values); if (results == null) { warn("failed to insert MMS part"); return null; } debug("Inserted" + results); return results; } Loading @@ -415,17 +428,23 @@ class MapClientContent { Uri contentUri = Uri.parse(messageUri.toString() + "/addr"); String originator = getOriginatorNumber(message); values.put(Mms.Addr.CHARSET, DEFAULT_CHARSET); values.put(Mms.Addr.ADDRESS, originator); values.put(Mms.Addr.TYPE, ORIGINATOR_ADDRESS_TYPE); mResolver.insert(contentUri, values); Uri results = mResolver.insert(contentUri, values); if (results == null) { warn("failed to insert originator address"); } Set<String> messageContacts = new ArraySet<>(); getRecipientsFromMessage(message, messageContacts); for (String recipient : messageContacts) { values.put(Mms.Addr.ADDRESS, recipient); values.put(Mms.Addr.TYPE, RECIPIENT_ADDRESS_TYPE); mResolver.insert(contentUri, values); results = mResolver.insert(contentUri, values); if (results == null) { warn("failed to insert recipient address"); } } } Loading android/app/tests/unit/src/com/android/bluetooth/mapclient/MapClientContentTest.java +83 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import static com.google.common.truth.Truth.assertThat; import static org.mockito.Mockito.any; import static org.mockito.Mockito.anyInt; import static org.mockito.Mockito.anyString; import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.eq; import static org.mockito.Mockito.never; Loading Loading @@ -465,6 +466,50 @@ public class MapClientContentTest { MapClientContent.clearAllContent(mMockContext); } /** Test that we gracefully exit when there's a problem with the SMS/MMS DB being available */ @Test public void testInsertSmsFails_messageHandleNotInteractable() { // Try to store an MMS, but make the content resolver fail to insert and provide a null URI MissingContentProvider missingContentProvider = Mockito.spy(new MissingContentProvider(mMockContext)); mMockContentResolver.addProvider("sms", missingContentProvider); mMapClientContent = new MapClientContent(mMockContext, mCallbacks, mTestDevice); mMapClientContent.storeMessage( mTestMessage1, mTestMessage1Handle, mTestMessage1Timestamp, MESSAGE_SEEN); // Because the insert failed, function calls to update or delete this message should not // work either mMapClientContent.markRead(mTestMessage1Handle); verify(missingContentProvider, never()) .update(any(Uri.class), any(ContentValues.class), any(Bundle.class)); mMapClientContent.deleteMessage(mTestMessage1Handle); verify(missingContentProvider, never()) .delete(any(Uri.class), anyString(), any(String[].class)); } /** Test that we gracefully exit when there's a problem with the SMS/MMS DB being available */ @Test public void testInsertMmsPartsSkippedWhenMmsInsertFails_messageHandleNotInteractable() { // Try to store an MMS, but make the content resolver fail to insert and provide a null URI MissingContentProvider missingContentProvider = Mockito.spy(new MissingContentProvider(mMockContext)); mMockContentResolver.addProvider("mms", missingContentProvider); mMapClientContent = new MapClientContent(mMockContext, mCallbacks, mTestDevice); mMapClientContent.storeMessage( mTestMessage2, mTestMessage2Handle, mTestMessage1Timestamp, MESSAGE_SEEN); // Because the insert failed, function calls to update or delete this message should not // work either mMapClientContent.markRead(mTestMessage2Handle); verify(missingContentProvider, never()) .update(any(Uri.class), any(ContentValues.class), any(Bundle.class)); mMapClientContent.deleteMessage(mTestMessage2Handle); verify(missingContentProvider, never()) .delete(any(Uri.class), anyString(), any(String[].class)); } /** * Test verifying dumpsys does not cause Bluetooth to crash (esp since we're querying the * database to generate dump). Loading Loading @@ -550,4 +595,42 @@ public class MapClientContentTest { return 0; } } public class MissingContentProvider extends FakeContentProvider { MissingContentProvider(Context context) { super(context); } @Override public int delete(Uri uri, String selection, String[] selectionArgs) { // nothing deleted return 0; } @Override public Uri insert(Uri uri, ContentValues values) { // Insert fails, so there's no URI that points to the inserted values return null; } @Override public Cursor query( Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { // Return empty cursor Cursor cursor = Mockito.mock(Cursor.class); when(cursor.moveToFirst()).thenReturn(false); when(cursor.moveToNext()).thenReturn(false); return cursor; } @Override public int update(Uri uri, ContentValues values, Bundle extras) { // zero rows updated return 0; } } } Loading
android/app/src/com/android/bluetooth/mapclient/MapClientContent.java +25 −6 Original line number Diff line number Diff line Loading @@ -269,6 +269,11 @@ class MapClientContent { values.put(Sms.SEEN, seen); Uri results = mResolver.insert(contentUri, values); if (results == null) { error("Failed to get SMS URI, insert failed. Dropping message."); return; } mHandleToUriMap.put(handle, results); mUriToHandleMap.put(results, new MessageStatus(handle, readStatus)); debug("Map InsertedThread" + results); Loading Loading @@ -375,6 +380,11 @@ class MapClientContent { values.put(Mms.MESSAGE_SIZE, mmsBmessage.getSize()); Uri results = mResolver.insert(contentUri, values); if (results == null) { error("Failed to get MMS entry URI. Cannot store MMS parts. Dropping message."); return; } mHandleToUriMap.put(handle, results); mUriToHandleMap.put(results, new MessageStatus(handle, read)); Loading @@ -385,9 +395,6 @@ class MapClientContent { } storeAddressPart(message, results); values.put(Mms.Part.CONTENT_TYPE, "plain/text"); values.put(Mms.SUBSCRIPTION_ID, mSubscriptionId); } catch (Exception e) { error("Error while storing MMS: " + e.toString()); throw e; Loading @@ -406,6 +413,12 @@ class MapClientContent { Uri contentUri = Uri.parse(messageUri.toString() + "/part"); Uri results = mResolver.insert(contentUri, values); if (results == null) { warn("failed to insert MMS part"); return null; } debug("Inserted" + results); return results; } Loading @@ -415,17 +428,23 @@ class MapClientContent { Uri contentUri = Uri.parse(messageUri.toString() + "/addr"); String originator = getOriginatorNumber(message); values.put(Mms.Addr.CHARSET, DEFAULT_CHARSET); values.put(Mms.Addr.ADDRESS, originator); values.put(Mms.Addr.TYPE, ORIGINATOR_ADDRESS_TYPE); mResolver.insert(contentUri, values); Uri results = mResolver.insert(contentUri, values); if (results == null) { warn("failed to insert originator address"); } Set<String> messageContacts = new ArraySet<>(); getRecipientsFromMessage(message, messageContacts); for (String recipient : messageContacts) { values.put(Mms.Addr.ADDRESS, recipient); values.put(Mms.Addr.TYPE, RECIPIENT_ADDRESS_TYPE); mResolver.insert(contentUri, values); results = mResolver.insert(contentUri, values); if (results == null) { warn("failed to insert recipient address"); } } } Loading
android/app/tests/unit/src/com/android/bluetooth/mapclient/MapClientContentTest.java +83 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import static com.google.common.truth.Truth.assertThat; import static org.mockito.Mockito.any; import static org.mockito.Mockito.anyInt; import static org.mockito.Mockito.anyString; import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.eq; import static org.mockito.Mockito.never; Loading Loading @@ -465,6 +466,50 @@ public class MapClientContentTest { MapClientContent.clearAllContent(mMockContext); } /** Test that we gracefully exit when there's a problem with the SMS/MMS DB being available */ @Test public void testInsertSmsFails_messageHandleNotInteractable() { // Try to store an MMS, but make the content resolver fail to insert and provide a null URI MissingContentProvider missingContentProvider = Mockito.spy(new MissingContentProvider(mMockContext)); mMockContentResolver.addProvider("sms", missingContentProvider); mMapClientContent = new MapClientContent(mMockContext, mCallbacks, mTestDevice); mMapClientContent.storeMessage( mTestMessage1, mTestMessage1Handle, mTestMessage1Timestamp, MESSAGE_SEEN); // Because the insert failed, function calls to update or delete this message should not // work either mMapClientContent.markRead(mTestMessage1Handle); verify(missingContentProvider, never()) .update(any(Uri.class), any(ContentValues.class), any(Bundle.class)); mMapClientContent.deleteMessage(mTestMessage1Handle); verify(missingContentProvider, never()) .delete(any(Uri.class), anyString(), any(String[].class)); } /** Test that we gracefully exit when there's a problem with the SMS/MMS DB being available */ @Test public void testInsertMmsPartsSkippedWhenMmsInsertFails_messageHandleNotInteractable() { // Try to store an MMS, but make the content resolver fail to insert and provide a null URI MissingContentProvider missingContentProvider = Mockito.spy(new MissingContentProvider(mMockContext)); mMockContentResolver.addProvider("mms", missingContentProvider); mMapClientContent = new MapClientContent(mMockContext, mCallbacks, mTestDevice); mMapClientContent.storeMessage( mTestMessage2, mTestMessage2Handle, mTestMessage1Timestamp, MESSAGE_SEEN); // Because the insert failed, function calls to update or delete this message should not // work either mMapClientContent.markRead(mTestMessage2Handle); verify(missingContentProvider, never()) .update(any(Uri.class), any(ContentValues.class), any(Bundle.class)); mMapClientContent.deleteMessage(mTestMessage2Handle); verify(missingContentProvider, never()) .delete(any(Uri.class), anyString(), any(String[].class)); } /** * Test verifying dumpsys does not cause Bluetooth to crash (esp since we're querying the * database to generate dump). Loading Loading @@ -550,4 +595,42 @@ public class MapClientContentTest { return 0; } } public class MissingContentProvider extends FakeContentProvider { MissingContentProvider(Context context) { super(context); } @Override public int delete(Uri uri, String selection, String[] selectionArgs) { // nothing deleted return 0; } @Override public Uri insert(Uri uri, ContentValues values) { // Insert fails, so there's no URI that points to the inserted values return null; } @Override public Cursor query( Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { // Return empty cursor Cursor cursor = Mockito.mock(Cursor.class); when(cursor.moveToFirst()).thenReturn(false); when(cursor.moveToNext()).thenReturn(false); return cursor; } @Override public int update(Uri uri, ContentValues values, Bundle extras) { // zero rows updated return 0; } } }