Loading android/app/src/com/android/bluetooth/BluetoothMethodProxy.java +0 −10 Original line number Diff line number Diff line Loading @@ -41,7 +41,6 @@ import android.util.Log; import com.android.bluetooth.gatt.AppAdvertiseStats; import com.android.bluetooth.gatt.ContextMap; import com.android.bluetooth.gatt.GattService; import com.android.bluetooth.opp.BluetoothOppNotification; import com.android.internal.annotations.VisibleForTesting; import com.android.obex.HeaderSet; Loading Loading @@ -250,13 +249,4 @@ public class BluetoothMethodProxy { ContextMap map, GattService service) { return new AppAdvertiseStats(appUid, id, name, map, service); } /** * Proxies {@link com.android.bluetooth.opp.BluetoothOppNotification#BluetoothOppNotification( * Context)}. */ public BluetoothOppNotification newBluetoothOppNotification(final Context context) { return new BluetoothOppNotification(context); } } android/app/src/com/android/bluetooth/opp/BluetoothOppNotification.java +2 −2 Original line number Diff line number Diff line Loading @@ -61,7 +61,7 @@ import java.util.HashMap; * where there is an ongoing transfer, incoming transfer need confirm and * complete (successful or failed) transfer. */ public class BluetoothOppNotification { class BluetoothOppNotification { private static final String TAG = "BluetoothOppNotification"; private static final boolean V = Constants.VERBOSE; Loading Loading @@ -152,7 +152,7 @@ public class BluetoothOppNotification { * @param ctx The context to use to obtain access to the Notification * Service */ public BluetoothOppNotification(Context ctx) { BluetoothOppNotification(Context ctx) { mContext = ctx; mNotificationMgr = mContext.getSystemService(NotificationManager.class); mNotificationChannel = new NotificationChannel(OPP_NOTIFICATION_CHANNEL, Loading android/app/src/com/android/bluetooth/opp/BluetoothOppService.java +14 −21 Original line number Diff line number Diff line Loading @@ -55,7 +55,6 @@ import android.os.Process; import android.sysprop.BluetoothProperties; import android.util.Log; import com.android.bluetooth.BluetoothMethodProxy; import com.android.bluetooth.BluetoothObexTransport; import com.android.bluetooth.IObexConnectionHandler; import com.android.bluetooth.ObexServerSockets; Loading Loading @@ -129,8 +128,7 @@ public class BluetoothOppService extends ProfileService implements IObexConnecti private BluetoothShareContentObserver mObserver; /** Class to handle Notification Manager updates */ @VisibleForTesting BluetoothOppNotification mNotifier; private BluetoothOppNotification mNotifier; private boolean mPendingUpdate; Loading @@ -138,11 +136,9 @@ public class BluetoothOppService extends ProfileService implements IObexConnecti private boolean mUpdateThreadRunning; @VisibleForTesting ArrayList<BluetoothOppShareInfo> mShares; private ArrayList<BluetoothOppShareInfo> mShares; @VisibleForTesting ArrayList<BluetoothOppBatch> mBatches; private ArrayList<BluetoothOppBatch> mBatches; private BluetoothOppTransfer mTransfer; Loading Loading @@ -186,8 +182,7 @@ public class BluetoothOppService extends ProfileService implements IObexConnecti + BluetoothShare.USER_CONFIRMATION + "=" + BluetoothShare.USER_CONFIRMATION_PENDING; @VisibleForTesting static final String WHERE_INVISIBLE_UNCONFIRMED = private static final String WHERE_INVISIBLE_UNCONFIRMED = "(" + BluetoothShare.STATUS + " > " + BluetoothShare.STATUS_SUCCESS + " AND " + INVISIBLE + ") OR (" + WHERE_CONFIRM_PENDING_INBOUND + ")"; Loading Loading @@ -266,7 +261,7 @@ public class BluetoothOppService extends ProfileService implements IObexConnecti mAdapterService = AdapterService.getAdapterService(); mObserver = new BluetoothShareContentObserver(); getContentResolver().registerContentObserver(BluetoothShare.CONTENT_URI, true, mObserver); mNotifier = BluetoothMethodProxy.getInstance().newBluetoothOppNotification(this); mNotifier = new BluetoothOppNotification(this); mNotifier.mNotificationMgr.cancelAll(); mNotifier.updateNotification(); updateFromProvider(); Loading Loading @@ -995,9 +990,9 @@ public class BluetoothOppService extends ProfileService implements IObexConnecti /** * Removes the local copy of the info about a share. */ @VisibleForTesting void deleteShare(int arrayPos) { private void deleteShare(int arrayPos) { BluetoothOppShareInfo info = mShares.get(arrayPos); /* * Delete arrayPos from a batch. The logic is * 1) Search existing batch for the info Loading Loading @@ -1119,24 +1114,22 @@ public class BluetoothOppService extends ProfileService implements IObexConnecti } // Run in a background thread at boot. @VisibleForTesting static void trimDatabase(ContentResolver contentResolver) { private static void trimDatabase(ContentResolver contentResolver) { if (contentResolver.acquireContentProviderClient(BluetoothShare.CONTENT_URI) == null) { Log.w(TAG, "ContentProvider doesn't exist"); return; } // remove the invisible/unconfirmed inbound shares int delNum = BluetoothMethodProxy.getInstance().contentResolverDelete( contentResolver, BluetoothShare.CONTENT_URI, WHERE_INVISIBLE_UNCONFIRMED, null); int delNum = contentResolver.delete(BluetoothShare.CONTENT_URI, WHERE_INVISIBLE_UNCONFIRMED, null); if (V) { Log.v(TAG, "Deleted shares, number = " + delNum); } // Keep the latest inbound and successful shares. Cursor cursor = BluetoothMethodProxy.getInstance().contentResolverQuery( contentResolver, BluetoothShare.CONTENT_URI, new String[]{BluetoothShare._ID}, Cursor cursor = contentResolver.query(BluetoothShare.CONTENT_URI, new String[]{BluetoothShare._ID}, WHERE_INBOUND_SUCCESS, null, BluetoothShare._ID); // sort by id if (cursor == null) { return; Loading @@ -1148,8 +1141,8 @@ public class BluetoothOppService extends ProfileService implements IObexConnecti if (cursor.moveToPosition(numToDelete)) { int columnId = cursor.getColumnIndexOrThrow(BluetoothShare._ID); long id = cursor.getLong(columnId); delNum = BluetoothMethodProxy.getInstance().contentResolverDelete(contentResolver, BluetoothShare.CONTENT_URI, BluetoothShare._ID + " < " + id, null); delNum = contentResolver.delete(BluetoothShare.CONTENT_URI, BluetoothShare._ID + " < " + id, null); if (V) { Log.v(TAG, "Deleted old inbound success share: " + delNum); } Loading android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppServiceTest.java +8 −99 Original line number Diff line number Diff line Loading @@ -15,28 +15,17 @@ */ package com.android.bluetooth.opp; import static com.android.bluetooth.opp.BluetoothOppService.WHERE_INVISIBLE_UNCONFIRMED; import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.anyString; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import android.app.NotificationManager; import android.bluetooth.BluetoothAdapter; import android.content.ContentResolver; import android.database.MatrixCursor; import android.os.Handler; import android.content.Context; import androidx.test.platform.app.InstrumentationRegistry; import androidx.test.filters.MediumTest; import androidx.test.rule.ServiceTestRule; import androidx.test.runner.AndroidJUnit4; import com.android.bluetooth.BluetoothMethodProxy; import com.android.bluetooth.R; import com.android.bluetooth.TestUtils; import com.android.bluetooth.btservice.AdapterService; Loading @@ -50,33 +39,23 @@ import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockitoAnnotations; @MediumTest @RunWith(AndroidJUnit4.class) public class BluetoothOppServiceTest { @Rule public final ServiceTestRule mServiceRule = new ServiceTestRule(); @Mock BluetoothMethodProxy mMethodProxy; private BluetoothOppService mService = null; private BluetoothAdapter mAdapter = null; @Rule public final ServiceTestRule mServiceRule = new ServiceTestRule(); @Mock private AdapterService mAdapterService; @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); BluetoothMethodProxy.setInstanceForTesting(mMethodProxy); // To void mockito multi-thread inter-tests problem // If the thread still run in the next test, it will raise un-related mockito error BluetoothOppNotification bluetoothOppNotification = mock(BluetoothOppNotification.class); bluetoothOppNotification.mNotificationMgr = mock(NotificationManager.class); doReturn(bluetoothOppNotification).when(mMethodProxy).newBluetoothOppNotification(any()); TestUtils.setAdapterService(mAdapterService); doReturn(true, false).when(mAdapterService).isStartedProfile(anyString()); TestUtils.startService(mServiceRule, BluetoothOppService.class); mService = BluetoothOppService.getBluetoothOppService(); Assert.assertNotNull(mService); Loading @@ -87,7 +66,6 @@ public class BluetoothOppServiceTest { @After public void tearDown() throws Exception { BluetoothMethodProxy.setInstanceForTesting(null); TestUtils.stopService(mServiceRule, BluetoothOppService.class); TestUtils.clearAdapterService(mAdapterService); } Loading @@ -96,74 +74,5 @@ public class BluetoothOppServiceTest { public void testInitialize() { Assert.assertNotNull(BluetoothOppService.getBluetoothOppService()); } @Test public void deleteShare_deleteShareAndCorrespondingBatch() { int infoTimestamp = 123456789; int infoTimestamp2 = 123489; BluetoothOppShareInfo shareInfo = mock(BluetoothOppShareInfo.class); shareInfo.mTimestamp = infoTimestamp; shareInfo.mDestination = "AA:BB:CC:DD:EE:FF"; BluetoothOppShareInfo shareInfo2 = mock(BluetoothOppShareInfo.class); shareInfo2.mTimestamp = infoTimestamp2; shareInfo2.mDestination = "00:11:22:33:44:55"; mService.mShares.clear(); mService.mShares.add(shareInfo); mService.mShares.add(shareInfo2); // batch1 will be removed BluetoothOppBatch batch1 = new BluetoothOppBatch(mService, shareInfo); BluetoothOppBatch batch2 = new BluetoothOppBatch(mService, shareInfo2); batch2.mStatus = Constants.BATCH_STATUS_FINISHED; mService.mBatches.clear(); mService.mBatches.add(batch1); mService.mBatches.add(batch2); mService.deleteShare(0); assertThat(mService.mShares.size()).isEqualTo(1); assertThat(mService.mBatches.size()).isEqualTo(1); assertThat(mService.mShares.get(0)).isEqualTo(shareInfo2); assertThat(mService.mBatches.get(0)).isEqualTo(batch2); } @Test public void dump_shouldNotThrow() { BluetoothOppShareInfo info = mock(BluetoothOppShareInfo.class); mService.mShares.add(info); // should not throw mService.dump(new StringBuilder()); } @Test public void trimDatabase_trimsOldOrInvisibleRecords() { ContentResolver contentResolver = InstrumentationRegistry .getInstrumentation().getTargetContext().getContentResolver(); Assume.assumeTrue("Ignore test when there is no content provider", contentResolver.acquireContentProviderClient(BluetoothShare.CONTENT_URI) != null); doReturn(1 /* any int is Ok */).when(mMethodProxy).contentResolverDelete( eq(contentResolver), eq(BluetoothShare.CONTENT_URI), anyString(), any()); MatrixCursor cursor = new MatrixCursor(new String[]{BluetoothShare._ID}, 500); for (long i = 0; i < Constants.MAX_RECORDS_IN_DATABASE + 20; i++) { cursor.addRow(new Object[]{i}); } doReturn(cursor).when(mMethodProxy).contentResolverQuery(eq(contentResolver), eq(BluetoothShare.CONTENT_URI), any(), any(), any(), any()); BluetoothOppService.trimDatabase(contentResolver); // check trimmed invisible records verify(mMethodProxy).contentResolverDelete(eq(contentResolver), eq(BluetoothShare.CONTENT_URI), eq(WHERE_INVISIBLE_UNCONFIRMED), any()); // check trimmed old records verify(mMethodProxy).contentResolverDelete(eq(contentResolver), eq(BluetoothShare.CONTENT_URI), eq(BluetoothShare._ID + " < " + 20), any()); } } Loading
android/app/src/com/android/bluetooth/BluetoothMethodProxy.java +0 −10 Original line number Diff line number Diff line Loading @@ -41,7 +41,6 @@ import android.util.Log; import com.android.bluetooth.gatt.AppAdvertiseStats; import com.android.bluetooth.gatt.ContextMap; import com.android.bluetooth.gatt.GattService; import com.android.bluetooth.opp.BluetoothOppNotification; import com.android.internal.annotations.VisibleForTesting; import com.android.obex.HeaderSet; Loading Loading @@ -250,13 +249,4 @@ public class BluetoothMethodProxy { ContextMap map, GattService service) { return new AppAdvertiseStats(appUid, id, name, map, service); } /** * Proxies {@link com.android.bluetooth.opp.BluetoothOppNotification#BluetoothOppNotification( * Context)}. */ public BluetoothOppNotification newBluetoothOppNotification(final Context context) { return new BluetoothOppNotification(context); } }
android/app/src/com/android/bluetooth/opp/BluetoothOppNotification.java +2 −2 Original line number Diff line number Diff line Loading @@ -61,7 +61,7 @@ import java.util.HashMap; * where there is an ongoing transfer, incoming transfer need confirm and * complete (successful or failed) transfer. */ public class BluetoothOppNotification { class BluetoothOppNotification { private static final String TAG = "BluetoothOppNotification"; private static final boolean V = Constants.VERBOSE; Loading Loading @@ -152,7 +152,7 @@ public class BluetoothOppNotification { * @param ctx The context to use to obtain access to the Notification * Service */ public BluetoothOppNotification(Context ctx) { BluetoothOppNotification(Context ctx) { mContext = ctx; mNotificationMgr = mContext.getSystemService(NotificationManager.class); mNotificationChannel = new NotificationChannel(OPP_NOTIFICATION_CHANNEL, Loading
android/app/src/com/android/bluetooth/opp/BluetoothOppService.java +14 −21 Original line number Diff line number Diff line Loading @@ -55,7 +55,6 @@ import android.os.Process; import android.sysprop.BluetoothProperties; import android.util.Log; import com.android.bluetooth.BluetoothMethodProxy; import com.android.bluetooth.BluetoothObexTransport; import com.android.bluetooth.IObexConnectionHandler; import com.android.bluetooth.ObexServerSockets; Loading Loading @@ -129,8 +128,7 @@ public class BluetoothOppService extends ProfileService implements IObexConnecti private BluetoothShareContentObserver mObserver; /** Class to handle Notification Manager updates */ @VisibleForTesting BluetoothOppNotification mNotifier; private BluetoothOppNotification mNotifier; private boolean mPendingUpdate; Loading @@ -138,11 +136,9 @@ public class BluetoothOppService extends ProfileService implements IObexConnecti private boolean mUpdateThreadRunning; @VisibleForTesting ArrayList<BluetoothOppShareInfo> mShares; private ArrayList<BluetoothOppShareInfo> mShares; @VisibleForTesting ArrayList<BluetoothOppBatch> mBatches; private ArrayList<BluetoothOppBatch> mBatches; private BluetoothOppTransfer mTransfer; Loading Loading @@ -186,8 +182,7 @@ public class BluetoothOppService extends ProfileService implements IObexConnecti + BluetoothShare.USER_CONFIRMATION + "=" + BluetoothShare.USER_CONFIRMATION_PENDING; @VisibleForTesting static final String WHERE_INVISIBLE_UNCONFIRMED = private static final String WHERE_INVISIBLE_UNCONFIRMED = "(" + BluetoothShare.STATUS + " > " + BluetoothShare.STATUS_SUCCESS + " AND " + INVISIBLE + ") OR (" + WHERE_CONFIRM_PENDING_INBOUND + ")"; Loading Loading @@ -266,7 +261,7 @@ public class BluetoothOppService extends ProfileService implements IObexConnecti mAdapterService = AdapterService.getAdapterService(); mObserver = new BluetoothShareContentObserver(); getContentResolver().registerContentObserver(BluetoothShare.CONTENT_URI, true, mObserver); mNotifier = BluetoothMethodProxy.getInstance().newBluetoothOppNotification(this); mNotifier = new BluetoothOppNotification(this); mNotifier.mNotificationMgr.cancelAll(); mNotifier.updateNotification(); updateFromProvider(); Loading Loading @@ -995,9 +990,9 @@ public class BluetoothOppService extends ProfileService implements IObexConnecti /** * Removes the local copy of the info about a share. */ @VisibleForTesting void deleteShare(int arrayPos) { private void deleteShare(int arrayPos) { BluetoothOppShareInfo info = mShares.get(arrayPos); /* * Delete arrayPos from a batch. The logic is * 1) Search existing batch for the info Loading Loading @@ -1119,24 +1114,22 @@ public class BluetoothOppService extends ProfileService implements IObexConnecti } // Run in a background thread at boot. @VisibleForTesting static void trimDatabase(ContentResolver contentResolver) { private static void trimDatabase(ContentResolver contentResolver) { if (contentResolver.acquireContentProviderClient(BluetoothShare.CONTENT_URI) == null) { Log.w(TAG, "ContentProvider doesn't exist"); return; } // remove the invisible/unconfirmed inbound shares int delNum = BluetoothMethodProxy.getInstance().contentResolverDelete( contentResolver, BluetoothShare.CONTENT_URI, WHERE_INVISIBLE_UNCONFIRMED, null); int delNum = contentResolver.delete(BluetoothShare.CONTENT_URI, WHERE_INVISIBLE_UNCONFIRMED, null); if (V) { Log.v(TAG, "Deleted shares, number = " + delNum); } // Keep the latest inbound and successful shares. Cursor cursor = BluetoothMethodProxy.getInstance().contentResolverQuery( contentResolver, BluetoothShare.CONTENT_URI, new String[]{BluetoothShare._ID}, Cursor cursor = contentResolver.query(BluetoothShare.CONTENT_URI, new String[]{BluetoothShare._ID}, WHERE_INBOUND_SUCCESS, null, BluetoothShare._ID); // sort by id if (cursor == null) { return; Loading @@ -1148,8 +1141,8 @@ public class BluetoothOppService extends ProfileService implements IObexConnecti if (cursor.moveToPosition(numToDelete)) { int columnId = cursor.getColumnIndexOrThrow(BluetoothShare._ID); long id = cursor.getLong(columnId); delNum = BluetoothMethodProxy.getInstance().contentResolverDelete(contentResolver, BluetoothShare.CONTENT_URI, BluetoothShare._ID + " < " + id, null); delNum = contentResolver.delete(BluetoothShare.CONTENT_URI, BluetoothShare._ID + " < " + id, null); if (V) { Log.v(TAG, "Deleted old inbound success share: " + delNum); } Loading
android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppServiceTest.java +8 −99 Original line number Diff line number Diff line Loading @@ -15,28 +15,17 @@ */ package com.android.bluetooth.opp; import static com.android.bluetooth.opp.BluetoothOppService.WHERE_INVISIBLE_UNCONFIRMED; import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.anyString; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import android.app.NotificationManager; import android.bluetooth.BluetoothAdapter; import android.content.ContentResolver; import android.database.MatrixCursor; import android.os.Handler; import android.content.Context; import androidx.test.platform.app.InstrumentationRegistry; import androidx.test.filters.MediumTest; import androidx.test.rule.ServiceTestRule; import androidx.test.runner.AndroidJUnit4; import com.android.bluetooth.BluetoothMethodProxy; import com.android.bluetooth.R; import com.android.bluetooth.TestUtils; import com.android.bluetooth.btservice.AdapterService; Loading @@ -50,33 +39,23 @@ import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockitoAnnotations; @MediumTest @RunWith(AndroidJUnit4.class) public class BluetoothOppServiceTest { @Rule public final ServiceTestRule mServiceRule = new ServiceTestRule(); @Mock BluetoothMethodProxy mMethodProxy; private BluetoothOppService mService = null; private BluetoothAdapter mAdapter = null; @Rule public final ServiceTestRule mServiceRule = new ServiceTestRule(); @Mock private AdapterService mAdapterService; @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); BluetoothMethodProxy.setInstanceForTesting(mMethodProxy); // To void mockito multi-thread inter-tests problem // If the thread still run in the next test, it will raise un-related mockito error BluetoothOppNotification bluetoothOppNotification = mock(BluetoothOppNotification.class); bluetoothOppNotification.mNotificationMgr = mock(NotificationManager.class); doReturn(bluetoothOppNotification).when(mMethodProxy).newBluetoothOppNotification(any()); TestUtils.setAdapterService(mAdapterService); doReturn(true, false).when(mAdapterService).isStartedProfile(anyString()); TestUtils.startService(mServiceRule, BluetoothOppService.class); mService = BluetoothOppService.getBluetoothOppService(); Assert.assertNotNull(mService); Loading @@ -87,7 +66,6 @@ public class BluetoothOppServiceTest { @After public void tearDown() throws Exception { BluetoothMethodProxy.setInstanceForTesting(null); TestUtils.stopService(mServiceRule, BluetoothOppService.class); TestUtils.clearAdapterService(mAdapterService); } Loading @@ -96,74 +74,5 @@ public class BluetoothOppServiceTest { public void testInitialize() { Assert.assertNotNull(BluetoothOppService.getBluetoothOppService()); } @Test public void deleteShare_deleteShareAndCorrespondingBatch() { int infoTimestamp = 123456789; int infoTimestamp2 = 123489; BluetoothOppShareInfo shareInfo = mock(BluetoothOppShareInfo.class); shareInfo.mTimestamp = infoTimestamp; shareInfo.mDestination = "AA:BB:CC:DD:EE:FF"; BluetoothOppShareInfo shareInfo2 = mock(BluetoothOppShareInfo.class); shareInfo2.mTimestamp = infoTimestamp2; shareInfo2.mDestination = "00:11:22:33:44:55"; mService.mShares.clear(); mService.mShares.add(shareInfo); mService.mShares.add(shareInfo2); // batch1 will be removed BluetoothOppBatch batch1 = new BluetoothOppBatch(mService, shareInfo); BluetoothOppBatch batch2 = new BluetoothOppBatch(mService, shareInfo2); batch2.mStatus = Constants.BATCH_STATUS_FINISHED; mService.mBatches.clear(); mService.mBatches.add(batch1); mService.mBatches.add(batch2); mService.deleteShare(0); assertThat(mService.mShares.size()).isEqualTo(1); assertThat(mService.mBatches.size()).isEqualTo(1); assertThat(mService.mShares.get(0)).isEqualTo(shareInfo2); assertThat(mService.mBatches.get(0)).isEqualTo(batch2); } @Test public void dump_shouldNotThrow() { BluetoothOppShareInfo info = mock(BluetoothOppShareInfo.class); mService.mShares.add(info); // should not throw mService.dump(new StringBuilder()); } @Test public void trimDatabase_trimsOldOrInvisibleRecords() { ContentResolver contentResolver = InstrumentationRegistry .getInstrumentation().getTargetContext().getContentResolver(); Assume.assumeTrue("Ignore test when there is no content provider", contentResolver.acquireContentProviderClient(BluetoothShare.CONTENT_URI) != null); doReturn(1 /* any int is Ok */).when(mMethodProxy).contentResolverDelete( eq(contentResolver), eq(BluetoothShare.CONTENT_URI), anyString(), any()); MatrixCursor cursor = new MatrixCursor(new String[]{BluetoothShare._ID}, 500); for (long i = 0; i < Constants.MAX_RECORDS_IN_DATABASE + 20; i++) { cursor.addRow(new Object[]{i}); } doReturn(cursor).when(mMethodProxy).contentResolverQuery(eq(contentResolver), eq(BluetoothShare.CONTENT_URI), any(), any(), any(), any()); BluetoothOppService.trimDatabase(contentResolver); // check trimmed invisible records verify(mMethodProxy).contentResolverDelete(eq(contentResolver), eq(BluetoothShare.CONTENT_URI), eq(WHERE_INVISIBLE_UNCONFIRMED), any()); // check trimmed old records verify(mMethodProxy).contentResolverDelete(eq(contentResolver), eq(BluetoothShare.CONTENT_URI), eq(BluetoothShare._ID + " < " + 20), any()); } }