Loading android/app/src/com/android/bluetooth/BluetoothMethodProxy.java +27 −0 Original line number Diff line number Diff line Loading @@ -16,12 +16,16 @@ package com.android.bluetooth; import android.annotation.RequiresPermission; import android.bluetooth.BluetoothAdapter; import android.content.ContentResolver; import android.content.ContentValues; import android.content.Context; import android.content.Intent; import android.database.Cursor; import android.net.Uri; import android.os.Bundle; import android.os.CancellationSignal; import android.os.ParcelFileDescriptor; import android.util.Log; Loading Loading @@ -79,6 +83,23 @@ public class BluetoothMethodProxy { return contentResolver.query(contentUri, projection, selection, selectionArgs, sortOrder); } /** * Proxies {@link ContentResolver#query(Uri, String[], Bundle, CancellationSignal)}. */ public Cursor contentResolverQuery(ContentResolver contentResolver, final Uri contentUri, final String[] projection, final Bundle queryArgs, final CancellationSignal cancellationSignal) { return contentResolver.query(contentUri, projection, queryArgs, cancellationSignal); } /** * Proxies {@link ContentResolver#insert(Uri, ContentValues)}. */ public Uri contentResolverInsert(ContentResolver contentResolver, final Uri contentUri, final ContentValues contentValues) { return contentResolver.insert(contentUri, contentValues); } /** * Proxies {@link ContentResolver#update(Uri, ContentValues, String, String[])}. */ Loading Loading @@ -111,6 +132,12 @@ public class BluetoothMethodProxy { return contentResolver.openFileDescriptor(uri, mode); } /** * Proxies {@link Context#sendBroadcast(Intent)}. */ public void contextSendBroadcast(Context context, @RequiresPermission Intent intent) { context.sendBroadcast(intent); } /** * Proxies {@link HeaderSet#getHeader}. Loading android/app/src/com/android/bluetooth/hfp/AtPhonebook.java +16 −10 Original line number Diff line number Diff line Loading @@ -32,6 +32,7 @@ import android.provider.ContactsContract.PhoneLookup; import android.telephony.PhoneNumberUtils; import android.util.Log; import com.android.bluetooth.BluetoothMethodProxy; import com.android.bluetooth.R; import com.android.bluetooth.Utils; import com.android.bluetooth.util.DevicePolicyUtils; Loading Loading @@ -83,16 +84,20 @@ public class AtPhonebook { private Context mContext; private ContentResolver mContentResolver; private HeadsetNativeInterface mNativeInterface; private String mCurrentPhonebook; private String mCharacterSet = "UTF-8"; @VisibleForTesting String mCurrentPhonebook; @VisibleForTesting String mCharacterSet = "UTF-8"; private int mCpbrIndex1, mCpbrIndex2; @VisibleForTesting int mCpbrIndex1, mCpbrIndex2; private boolean mCheckingAccessPermission; // package and class name to which we send intent to check phone book access permission private final String mPairingPackage; private final HashMap<String, PhonebookResult> mPhonebooks = @VisibleForTesting final HashMap<String, PhonebookResult> mPhonebooks = new HashMap<String, PhonebookResult>(4); static final int TYPE_UNKNOWN = -1; Loading Loading @@ -434,8 +439,8 @@ public class AtPhonebook { queryArgs.putString(ContentResolver.QUERY_ARG_SQL_SELECTION, where); queryArgs.putString(ContentResolver.QUERY_ARG_SQL_SORT_ORDER, Calls.DEFAULT_SORT_ORDER); queryArgs.putInt(ContentResolver.QUERY_ARG_LIMIT, MAX_PHONEBOOK_SIZE); pbr.cursor = mContentResolver.query(Calls.CONTENT_URI, CALLS_PROJECTION, queryArgs, null); pbr.cursor = BluetoothMethodProxy.getInstance().contentResolverQuery(mContentResolver, Calls.CONTENT_URI, CALLS_PROJECTION, queryArgs, null); if (pbr.cursor == null) { return false; Loading @@ -450,8 +455,8 @@ public class AtPhonebook { queryArgs.putString(ContentResolver.QUERY_ARG_SQL_SELECTION, where); queryArgs.putInt(ContentResolver.QUERY_ARG_LIMIT, MAX_PHONEBOOK_SIZE); final Uri phoneContentUri = DevicePolicyUtils.getEnterprisePhoneUri(mContext); pbr.cursor = mContentResolver.query(phoneContentUri, PHONES_PROJECTION, queryArgs, null); pbr.cursor = BluetoothMethodProxy.getInstance().contentResolverQuery(mContentResolver, phoneContentUri, PHONES_PROJECTION, queryArgs, null); if (pbr.cursor == null) { return false; Loading Loading @@ -547,7 +552,7 @@ public class AtPhonebook { // try caller id lookup // TODO: This code is horribly inefficient. I saw it // take 7 seconds to process 100 missed calls. Cursor c = mContentResolver.query( Cursor c = BluetoothMethodProxy.getInstance().contentResolverQuery(mContentResolver, Uri.withAppendedPath(PhoneLookup.ENTERPRISE_CONTENT_FILTER_URI, number), new String[]{ PhoneLookup.DISPLAY_NAME, PhoneLookup.TYPE Loading Loading @@ -658,7 +663,8 @@ public class AtPhonebook { return permission; } private static String getPhoneType(int type) { @VisibleForTesting static String getPhoneType(int type) { switch (type) { case Phone.TYPE_HOME: return "H"; Loading android/app/tests/unit/src/com/android/bluetooth/hfp/AtPhonebookTest.java +131 −0 Original line number Diff line number Diff line Loading @@ -18,19 +18,30 @@ package com.android.bluetooth.hfp; import static com.google.common.truth.Truth.assertThat; import static org.mockito.Mockito.any; import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.content.Context; import android.database.Cursor; import android.provider.CallLog; import android.provider.ContactsContract.CommonDataKinds.Phone; import android.telephony.PhoneNumberUtils; import androidx.test.InstrumentationRegistry; 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; import com.android.internal.telephony.GsmAlphabet; import org.junit.After; import org.junit.Before; Loading @@ -38,6 +49,7 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.mockito.Spy; @RunWith(AndroidJUnit4.class) public class AtPhonebookTest { Loading @@ -50,6 +62,8 @@ public class AtPhonebookTest { private AdapterService mAdapterService; private HeadsetNativeInterface mNativeInterface; private AtPhonebook mAtPhonebook; @Spy private BluetoothMethodProxy mHfpMethodProxy = BluetoothMethodProxy.getInstance(); @Before public void setUp() throws Exception { Loading @@ -57,6 +71,7 @@ public class AtPhonebookTest { MockitoAnnotations.initMocks(this); TestUtils.setAdapterService(mAdapterService); BluetoothMethodProxy.setInstanceForTesting(mHfpMethodProxy); mAdapter = BluetoothAdapter.getDefaultAdapter(); mTestDevice = mAdapter.getRemoteDevice("00:01:02:03:04:05"); // Spy on native interface Loading @@ -67,6 +82,7 @@ public class AtPhonebookTest { @After public void tearDown() throws Exception { TestUtils.clearAdapterService(mAdapterService); BluetoothMethodProxy.setInstanceForTesting(null); } @Test Loading @@ -78,6 +94,7 @@ public class AtPhonebookTest { @Test public void getAndSetCheckingAccessPermission_setCorrectly() { mAtPhonebook.setCheckingAccessPermission(true); assertThat(mAtPhonebook.getCheckingAccessPermission()).isTrue(); } Loading Loading @@ -173,11 +190,125 @@ public class AtPhonebookTest { mAtPhonebook.handleCpbsCommand("command=ME", AtPhonebook.TYPE_SET, mTestDevice); assertThat(mAtPhonebook.processCpbrCommand(mTestDevice)).isEqualTo( HeadsetHalConstants.AT_RESPONSE_OK); mAtPhonebook.mCurrentPhonebook = "ER"; assertThat(mAtPhonebook.processCpbrCommand(mTestDevice)).isEqualTo( HeadsetHalConstants.AT_RESPONSE_ERROR); } @Test public void processCpbrCommand_withMobilePhonebook() { Cursor mockCursorOne = mock(Cursor.class); when(mockCursorOne.getCount()).thenReturn(1); when(mockCursorOne.getColumnIndex(Phone.TYPE)).thenReturn(1); //TypeColumn when(mockCursorOne.getColumnIndex(Phone.NUMBER)).thenReturn(2); //numberColumn when(mockCursorOne.getColumnIndex(Phone.DISPLAY_NAME)).thenReturn(3); // nameColumn when(mockCursorOne.getInt(1)).thenReturn(Phone.TYPE_WORK); when(mockCursorOne.getString(2)).thenReturn(null); when(mockCursorOne.getString(3)).thenReturn(null); when(mockCursorOne.moveToNext()).thenReturn(false); doReturn(mockCursorOne).when(mHfpMethodProxy).contentResolverQuery(any(), any(), any(), any(), any()); mAtPhonebook.mCurrentPhonebook = "ME"; mAtPhonebook.mCpbrIndex1 = 1; mAtPhonebook.mCpbrIndex2 = 2; mAtPhonebook.processCpbrCommand(mTestDevice); String expected = "+CPBR: " + 1 + ",\"" + "" + "\"," + PhoneNumberUtils.toaFromString("") + ",\"" + "" + "/" + AtPhonebook.getPhoneType(Phone.TYPE_WORK) + "\"" + "\r\n\r\n"; verify(mNativeInterface).atResponseString(mTestDevice, expected); } @Test public void processCpbrCommand_withMissedCalls() { Cursor mockCursorOne = mock(Cursor.class); when(mockCursorOne.getCount()).thenReturn(1); when(mockCursorOne.getColumnIndexOrThrow(CallLog.Calls.NUMBER)).thenReturn(1); when(mockCursorOne.getColumnIndexOrThrow(CallLog.Calls.NUMBER_PRESENTATION)).thenReturn(2); String number = "1".repeat(31); when(mockCursorOne.getString(1)).thenReturn(number); when(mockCursorOne.getInt(2)).thenReturn(CallLog.Calls.PRESENTATION_RESTRICTED); doReturn(mockCursorOne).when(mHfpMethodProxy).contentResolverQuery(any(), any(), any(), any(), any()); Cursor mockCursorTwo = mock(Cursor.class); when(mockCursorTwo.moveToFirst()).thenReturn(true); String name = "k".repeat(30); when(mockCursorTwo.getString(0)).thenReturn(name); when(mockCursorTwo.getInt(1)).thenReturn(1); doReturn(mockCursorTwo).when(mHfpMethodProxy).contentResolverQuery(any(), any(), any(), any(), any(), any()); mAtPhonebook.mCurrentPhonebook = "MC"; mAtPhonebook.mCpbrIndex1 = 1; mAtPhonebook.mCpbrIndex2 = 2; mAtPhonebook.processCpbrCommand(mTestDevice); String expected = "+CPBR: " + 1 + ",\"" + "" + "\"," + PhoneNumberUtils.toaFromString( number) + ",\"" + mTargetContext.getString(R.string.unknownNumber) + "\"" + "\r\n\r\n"; verify(mNativeInterface).atResponseString(mTestDevice, expected); } @Test public void processCpbrCommand_withReceivcedCallsAndCharsetGsm() { Cursor mockCursorOne = mock(Cursor.class); when(mockCursorOne.getCount()).thenReturn(1); when(mockCursorOne.getColumnIndexOrThrow(CallLog.Calls.NUMBER)).thenReturn(1); when(mockCursorOne.getColumnIndexOrThrow(CallLog.Calls.NUMBER_PRESENTATION)).thenReturn(-1); String number = "1".repeat(31); when(mockCursorOne.getString(1)).thenReturn(number); when(mockCursorOne.getInt(2)).thenReturn(CallLog.Calls.PRESENTATION_RESTRICTED); doReturn(mockCursorOne).when(mHfpMethodProxy).contentResolverQuery(any(), any(), any(), any(), any()); Cursor mockCursorTwo = mock(Cursor.class); when(mockCursorTwo.moveToFirst()).thenReturn(true); String name = "k".repeat(30); when(mockCursorTwo.getString(0)).thenReturn(name); when(mockCursorTwo.getInt(1)).thenReturn(1); doReturn(mockCursorTwo).when(mHfpMethodProxy).contentResolverQuery(any(), any(), any(), any(), any(), any()); mAtPhonebook.mCurrentPhonebook = "RC"; mAtPhonebook.mCpbrIndex1 = 1; mAtPhonebook.mCpbrIndex2 = 2; mAtPhonebook.mCharacterSet = "GSM"; mAtPhonebook.processCpbrCommand(mTestDevice); String expectedName = new String(GsmAlphabet.stringToGsm8BitPacked(name.substring(0, 28))); String expected = "+CPBR: " + 1 + ",\"" + number.substring(0, 30) + "\"," + PhoneNumberUtils.toaFromString(number) + ",\"" + expectedName + "\"" + "\r\n\r\n"; verify(mNativeInterface).atResponseString(mTestDevice, expected); } @Test public void setCpbrIndex() { int index = 1; mAtPhonebook.setCpbrIndex(index); assertThat(mAtPhonebook.mCpbrIndex1).isEqualTo(index); assertThat(mAtPhonebook.mCpbrIndex2).isEqualTo(index); } @Test public void resetAtState() { mAtPhonebook.resetAtState(); assertThat(mAtPhonebook.getCheckingAccessPermission()).isFalse(); } @Test public void getPhoneType() { assertThat(AtPhonebook.getPhoneType(Phone.TYPE_HOME)).isEqualTo("H"); assertThat(AtPhonebook.getPhoneType(Phone.TYPE_MOBILE)).isEqualTo("M"); assertThat(AtPhonebook.getPhoneType(Phone.TYPE_WORK)).isEqualTo("W"); assertThat(AtPhonebook.getPhoneType(Phone.TYPE_FAX_WORK)).isEqualTo("F"); assertThat(AtPhonebook.getPhoneType(Phone.TYPE_CUSTOM)).isEqualTo("O"); } } No newline at end of file Loading
android/app/src/com/android/bluetooth/BluetoothMethodProxy.java +27 −0 Original line number Diff line number Diff line Loading @@ -16,12 +16,16 @@ package com.android.bluetooth; import android.annotation.RequiresPermission; import android.bluetooth.BluetoothAdapter; import android.content.ContentResolver; import android.content.ContentValues; import android.content.Context; import android.content.Intent; import android.database.Cursor; import android.net.Uri; import android.os.Bundle; import android.os.CancellationSignal; import android.os.ParcelFileDescriptor; import android.util.Log; Loading Loading @@ -79,6 +83,23 @@ public class BluetoothMethodProxy { return contentResolver.query(contentUri, projection, selection, selectionArgs, sortOrder); } /** * Proxies {@link ContentResolver#query(Uri, String[], Bundle, CancellationSignal)}. */ public Cursor contentResolverQuery(ContentResolver contentResolver, final Uri contentUri, final String[] projection, final Bundle queryArgs, final CancellationSignal cancellationSignal) { return contentResolver.query(contentUri, projection, queryArgs, cancellationSignal); } /** * Proxies {@link ContentResolver#insert(Uri, ContentValues)}. */ public Uri contentResolverInsert(ContentResolver contentResolver, final Uri contentUri, final ContentValues contentValues) { return contentResolver.insert(contentUri, contentValues); } /** * Proxies {@link ContentResolver#update(Uri, ContentValues, String, String[])}. */ Loading Loading @@ -111,6 +132,12 @@ public class BluetoothMethodProxy { return contentResolver.openFileDescriptor(uri, mode); } /** * Proxies {@link Context#sendBroadcast(Intent)}. */ public void contextSendBroadcast(Context context, @RequiresPermission Intent intent) { context.sendBroadcast(intent); } /** * Proxies {@link HeaderSet#getHeader}. Loading
android/app/src/com/android/bluetooth/hfp/AtPhonebook.java +16 −10 Original line number Diff line number Diff line Loading @@ -32,6 +32,7 @@ import android.provider.ContactsContract.PhoneLookup; import android.telephony.PhoneNumberUtils; import android.util.Log; import com.android.bluetooth.BluetoothMethodProxy; import com.android.bluetooth.R; import com.android.bluetooth.Utils; import com.android.bluetooth.util.DevicePolicyUtils; Loading Loading @@ -83,16 +84,20 @@ public class AtPhonebook { private Context mContext; private ContentResolver mContentResolver; private HeadsetNativeInterface mNativeInterface; private String mCurrentPhonebook; private String mCharacterSet = "UTF-8"; @VisibleForTesting String mCurrentPhonebook; @VisibleForTesting String mCharacterSet = "UTF-8"; private int mCpbrIndex1, mCpbrIndex2; @VisibleForTesting int mCpbrIndex1, mCpbrIndex2; private boolean mCheckingAccessPermission; // package and class name to which we send intent to check phone book access permission private final String mPairingPackage; private final HashMap<String, PhonebookResult> mPhonebooks = @VisibleForTesting final HashMap<String, PhonebookResult> mPhonebooks = new HashMap<String, PhonebookResult>(4); static final int TYPE_UNKNOWN = -1; Loading Loading @@ -434,8 +439,8 @@ public class AtPhonebook { queryArgs.putString(ContentResolver.QUERY_ARG_SQL_SELECTION, where); queryArgs.putString(ContentResolver.QUERY_ARG_SQL_SORT_ORDER, Calls.DEFAULT_SORT_ORDER); queryArgs.putInt(ContentResolver.QUERY_ARG_LIMIT, MAX_PHONEBOOK_SIZE); pbr.cursor = mContentResolver.query(Calls.CONTENT_URI, CALLS_PROJECTION, queryArgs, null); pbr.cursor = BluetoothMethodProxy.getInstance().contentResolverQuery(mContentResolver, Calls.CONTENT_URI, CALLS_PROJECTION, queryArgs, null); if (pbr.cursor == null) { return false; Loading @@ -450,8 +455,8 @@ public class AtPhonebook { queryArgs.putString(ContentResolver.QUERY_ARG_SQL_SELECTION, where); queryArgs.putInt(ContentResolver.QUERY_ARG_LIMIT, MAX_PHONEBOOK_SIZE); final Uri phoneContentUri = DevicePolicyUtils.getEnterprisePhoneUri(mContext); pbr.cursor = mContentResolver.query(phoneContentUri, PHONES_PROJECTION, queryArgs, null); pbr.cursor = BluetoothMethodProxy.getInstance().contentResolverQuery(mContentResolver, phoneContentUri, PHONES_PROJECTION, queryArgs, null); if (pbr.cursor == null) { return false; Loading Loading @@ -547,7 +552,7 @@ public class AtPhonebook { // try caller id lookup // TODO: This code is horribly inefficient. I saw it // take 7 seconds to process 100 missed calls. Cursor c = mContentResolver.query( Cursor c = BluetoothMethodProxy.getInstance().contentResolverQuery(mContentResolver, Uri.withAppendedPath(PhoneLookup.ENTERPRISE_CONTENT_FILTER_URI, number), new String[]{ PhoneLookup.DISPLAY_NAME, PhoneLookup.TYPE Loading Loading @@ -658,7 +663,8 @@ public class AtPhonebook { return permission; } private static String getPhoneType(int type) { @VisibleForTesting static String getPhoneType(int type) { switch (type) { case Phone.TYPE_HOME: return "H"; Loading
android/app/tests/unit/src/com/android/bluetooth/hfp/AtPhonebookTest.java +131 −0 Original line number Diff line number Diff line Loading @@ -18,19 +18,30 @@ package com.android.bluetooth.hfp; import static com.google.common.truth.Truth.assertThat; import static org.mockito.Mockito.any; import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.content.Context; import android.database.Cursor; import android.provider.CallLog; import android.provider.ContactsContract.CommonDataKinds.Phone; import android.telephony.PhoneNumberUtils; import androidx.test.InstrumentationRegistry; 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; import com.android.internal.telephony.GsmAlphabet; import org.junit.After; import org.junit.Before; Loading @@ -38,6 +49,7 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.mockito.Spy; @RunWith(AndroidJUnit4.class) public class AtPhonebookTest { Loading @@ -50,6 +62,8 @@ public class AtPhonebookTest { private AdapterService mAdapterService; private HeadsetNativeInterface mNativeInterface; private AtPhonebook mAtPhonebook; @Spy private BluetoothMethodProxy mHfpMethodProxy = BluetoothMethodProxy.getInstance(); @Before public void setUp() throws Exception { Loading @@ -57,6 +71,7 @@ public class AtPhonebookTest { MockitoAnnotations.initMocks(this); TestUtils.setAdapterService(mAdapterService); BluetoothMethodProxy.setInstanceForTesting(mHfpMethodProxy); mAdapter = BluetoothAdapter.getDefaultAdapter(); mTestDevice = mAdapter.getRemoteDevice("00:01:02:03:04:05"); // Spy on native interface Loading @@ -67,6 +82,7 @@ public class AtPhonebookTest { @After public void tearDown() throws Exception { TestUtils.clearAdapterService(mAdapterService); BluetoothMethodProxy.setInstanceForTesting(null); } @Test Loading @@ -78,6 +94,7 @@ public class AtPhonebookTest { @Test public void getAndSetCheckingAccessPermission_setCorrectly() { mAtPhonebook.setCheckingAccessPermission(true); assertThat(mAtPhonebook.getCheckingAccessPermission()).isTrue(); } Loading Loading @@ -173,11 +190,125 @@ public class AtPhonebookTest { mAtPhonebook.handleCpbsCommand("command=ME", AtPhonebook.TYPE_SET, mTestDevice); assertThat(mAtPhonebook.processCpbrCommand(mTestDevice)).isEqualTo( HeadsetHalConstants.AT_RESPONSE_OK); mAtPhonebook.mCurrentPhonebook = "ER"; assertThat(mAtPhonebook.processCpbrCommand(mTestDevice)).isEqualTo( HeadsetHalConstants.AT_RESPONSE_ERROR); } @Test public void processCpbrCommand_withMobilePhonebook() { Cursor mockCursorOne = mock(Cursor.class); when(mockCursorOne.getCount()).thenReturn(1); when(mockCursorOne.getColumnIndex(Phone.TYPE)).thenReturn(1); //TypeColumn when(mockCursorOne.getColumnIndex(Phone.NUMBER)).thenReturn(2); //numberColumn when(mockCursorOne.getColumnIndex(Phone.DISPLAY_NAME)).thenReturn(3); // nameColumn when(mockCursorOne.getInt(1)).thenReturn(Phone.TYPE_WORK); when(mockCursorOne.getString(2)).thenReturn(null); when(mockCursorOne.getString(3)).thenReturn(null); when(mockCursorOne.moveToNext()).thenReturn(false); doReturn(mockCursorOne).when(mHfpMethodProxy).contentResolverQuery(any(), any(), any(), any(), any()); mAtPhonebook.mCurrentPhonebook = "ME"; mAtPhonebook.mCpbrIndex1 = 1; mAtPhonebook.mCpbrIndex2 = 2; mAtPhonebook.processCpbrCommand(mTestDevice); String expected = "+CPBR: " + 1 + ",\"" + "" + "\"," + PhoneNumberUtils.toaFromString("") + ",\"" + "" + "/" + AtPhonebook.getPhoneType(Phone.TYPE_WORK) + "\"" + "\r\n\r\n"; verify(mNativeInterface).atResponseString(mTestDevice, expected); } @Test public void processCpbrCommand_withMissedCalls() { Cursor mockCursorOne = mock(Cursor.class); when(mockCursorOne.getCount()).thenReturn(1); when(mockCursorOne.getColumnIndexOrThrow(CallLog.Calls.NUMBER)).thenReturn(1); when(mockCursorOne.getColumnIndexOrThrow(CallLog.Calls.NUMBER_PRESENTATION)).thenReturn(2); String number = "1".repeat(31); when(mockCursorOne.getString(1)).thenReturn(number); when(mockCursorOne.getInt(2)).thenReturn(CallLog.Calls.PRESENTATION_RESTRICTED); doReturn(mockCursorOne).when(mHfpMethodProxy).contentResolverQuery(any(), any(), any(), any(), any()); Cursor mockCursorTwo = mock(Cursor.class); when(mockCursorTwo.moveToFirst()).thenReturn(true); String name = "k".repeat(30); when(mockCursorTwo.getString(0)).thenReturn(name); when(mockCursorTwo.getInt(1)).thenReturn(1); doReturn(mockCursorTwo).when(mHfpMethodProxy).contentResolverQuery(any(), any(), any(), any(), any(), any()); mAtPhonebook.mCurrentPhonebook = "MC"; mAtPhonebook.mCpbrIndex1 = 1; mAtPhonebook.mCpbrIndex2 = 2; mAtPhonebook.processCpbrCommand(mTestDevice); String expected = "+CPBR: " + 1 + ",\"" + "" + "\"," + PhoneNumberUtils.toaFromString( number) + ",\"" + mTargetContext.getString(R.string.unknownNumber) + "\"" + "\r\n\r\n"; verify(mNativeInterface).atResponseString(mTestDevice, expected); } @Test public void processCpbrCommand_withReceivcedCallsAndCharsetGsm() { Cursor mockCursorOne = mock(Cursor.class); when(mockCursorOne.getCount()).thenReturn(1); when(mockCursorOne.getColumnIndexOrThrow(CallLog.Calls.NUMBER)).thenReturn(1); when(mockCursorOne.getColumnIndexOrThrow(CallLog.Calls.NUMBER_PRESENTATION)).thenReturn(-1); String number = "1".repeat(31); when(mockCursorOne.getString(1)).thenReturn(number); when(mockCursorOne.getInt(2)).thenReturn(CallLog.Calls.PRESENTATION_RESTRICTED); doReturn(mockCursorOne).when(mHfpMethodProxy).contentResolverQuery(any(), any(), any(), any(), any()); Cursor mockCursorTwo = mock(Cursor.class); when(mockCursorTwo.moveToFirst()).thenReturn(true); String name = "k".repeat(30); when(mockCursorTwo.getString(0)).thenReturn(name); when(mockCursorTwo.getInt(1)).thenReturn(1); doReturn(mockCursorTwo).when(mHfpMethodProxy).contentResolverQuery(any(), any(), any(), any(), any(), any()); mAtPhonebook.mCurrentPhonebook = "RC"; mAtPhonebook.mCpbrIndex1 = 1; mAtPhonebook.mCpbrIndex2 = 2; mAtPhonebook.mCharacterSet = "GSM"; mAtPhonebook.processCpbrCommand(mTestDevice); String expectedName = new String(GsmAlphabet.stringToGsm8BitPacked(name.substring(0, 28))); String expected = "+CPBR: " + 1 + ",\"" + number.substring(0, 30) + "\"," + PhoneNumberUtils.toaFromString(number) + ",\"" + expectedName + "\"" + "\r\n\r\n"; verify(mNativeInterface).atResponseString(mTestDevice, expected); } @Test public void setCpbrIndex() { int index = 1; mAtPhonebook.setCpbrIndex(index); assertThat(mAtPhonebook.mCpbrIndex1).isEqualTo(index); assertThat(mAtPhonebook.mCpbrIndex2).isEqualTo(index); } @Test public void resetAtState() { mAtPhonebook.resetAtState(); assertThat(mAtPhonebook.getCheckingAccessPermission()).isFalse(); } @Test public void getPhoneType() { assertThat(AtPhonebook.getPhoneType(Phone.TYPE_HOME)).isEqualTo("H"); assertThat(AtPhonebook.getPhoneType(Phone.TYPE_MOBILE)).isEqualTo("M"); assertThat(AtPhonebook.getPhoneType(Phone.TYPE_WORK)).isEqualTo("W"); assertThat(AtPhonebook.getPhoneType(Phone.TYPE_FAX_WORK)).isEqualTo("F"); assertThat(AtPhonebook.getPhoneType(Phone.TYPE_CUSTOM)).isEqualTo("O"); } } No newline at end of file