Loading android/app/src/com/android/bluetooth/BluetoothMethodProxy.java +7 −0 Original line number Original line Diff line number Diff line Loading @@ -178,6 +178,13 @@ public class BluetoothMethodProxy { context.sendBroadcast(intent); context.sendBroadcast(intent); } } /** * Proxies {@link Handler#sendEmptyMessage(int)}}. */ public boolean handlerSendEmptyMessage(Handler handler, final int what) { return handler.sendEmptyMessage(what); } /** /** * Proxies {@link HeaderSet#getHeader}. * Proxies {@link HeaderSet#getHeader}. */ */ Loading android/app/src/com/android/bluetooth/opp/BluetoothOppTransfer.java +23 −11 Original line number Original line Diff line number Diff line Loading @@ -92,23 +92,27 @@ public class BluetoothOppTransfer implements BluetoothOppBatch.BluetoothOppBatch private BluetoothAdapter mAdapter; private BluetoothAdapter mAdapter; private BluetoothDevice mDevice; @VisibleForTesting BluetoothDevice mDevice; private BluetoothOppBatch mBatch; private BluetoothOppBatch mBatch; private BluetoothOppObexSession mSession; private BluetoothOppObexSession mSession; private BluetoothOppShareInfo mCurrentShare; @VisibleForTesting BluetoothOppShareInfo mCurrentShare; private ObexTransport mTransport; private ObexTransport mTransport; private HandlerThread mHandlerThread; private HandlerThread mHandlerThread; private EventHandler mSessionHandler; @VisibleForTesting EventHandler mSessionHandler; private long mTimestamp; private long mTimestamp; private class OppConnectionReceiver extends BroadcastReceiver { @VisibleForTesting class OppConnectionReceiver extends BroadcastReceiver { @Override @Override public void onReceive(Context context, Intent intent) { public void onReceive(Context context, Intent intent) { String action = intent.getAction(); String action = intent.getAction(); Loading Loading @@ -139,8 +143,8 @@ public class BluetoothOppTransfer implements BluetoothOppBatch.BluetoothOppBatch // Remove the timeout message triggered earlier during Obex Put // Remove the timeout message triggered earlier during Obex Put mSessionHandler.removeMessages(BluetoothOppObexSession.MSG_CONNECT_TIMEOUT); mSessionHandler.removeMessages(BluetoothOppObexSession.MSG_CONNECT_TIMEOUT); // Now reuse the same message to clean up the session. // Now reuse the same message to clean up the session. mSessionHandler.sendMessage(mSessionHandler.obtainMessage( BluetoothMethodProxy.getInstance().handlerSendEmptyMessage(mSessionHandler, BluetoothOppObexSession.MSG_CONNECT_TIMEOUT)); BluetoothOppObexSession.MSG_CONNECT_TIMEOUT); } } } catch (Exception e) { } catch (Exception e) { e.printStackTrace(); e.printStackTrace(); Loading @@ -160,7 +164,11 @@ public class BluetoothOppTransfer implements BluetoothOppBatch.BluetoothOppBatch Log.w(TAG, "OPP SDP search, target device is null, ignoring result"); Log.w(TAG, "OPP SDP search, target device is null, ignoring result"); return; return; } } if (!device.getIdentityAddress().equalsIgnoreCase(mDevice.getIdentityAddress())) { String deviceIdentityAddress = device.getIdentityAddress(); String transferDeviceIdentityAddress = mDevice.getIdentityAddress(); if (deviceIdentityAddress == null || transferDeviceIdentityAddress == null || !deviceIdentityAddress.equalsIgnoreCase( transferDeviceIdentityAddress)) { Log.w(TAG, " OPP SDP search for wrong device, ignoring!!"); Log.w(TAG, " OPP SDP search for wrong device, ignoring!!"); return; return; } } Loading Loading @@ -676,10 +684,12 @@ public class BluetoothOppTransfer implements BluetoothOppBatch.BluetoothOppBatch @VisibleForTesting @VisibleForTesting SocketConnectThread mConnectThread; SocketConnectThread mConnectThread; private class SocketConnectThread extends Thread { @VisibleForTesting class SocketConnectThread extends Thread { private final String mHost; private final String mHost; private final BluetoothDevice mDevice; @VisibleForTesting final BluetoothDevice mDevice; private final int mChannel; private final int mChannel; Loading @@ -695,7 +705,8 @@ public class BluetoothOppTransfer implements BluetoothOppBatch.BluetoothOppBatch private boolean mSdpInitiated = false; private boolean mSdpInitiated = false; private boolean mIsInterrupted = false; @VisibleForTesting boolean mIsInterrupted = false; /* create a Rfcomm/L2CAP Socket */ /* create a Rfcomm/L2CAP Socket */ SocketConnectThread(BluetoothDevice device, boolean retry) { SocketConnectThread(BluetoothDevice device, boolean retry) { Loading Loading @@ -863,7 +874,8 @@ public class BluetoothOppTransfer implements BluetoothOppBatch.BluetoothOppBatch Log.e(TAG, "Error when close socket"); Log.e(TAG, "Error when close socket"); } } } } mSessionHandler.obtainMessage(TRANSPORT_ERROR).sendToTarget(); BluetoothMethodProxy.getInstance().handlerSendEmptyMessage(mSessionHandler, TRANSPORT_ERROR); return; return; } } Loading android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppTransferTest.java +90 −3 Original line number Original line Diff line number Diff line Loading @@ -21,6 +21,7 @@ import static com.android.bluetooth.opp.BluetoothOppTransfer.TRANSPORT_ERROR; import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.nullable; import static org.mockito.ArgumentMatchers.nullable; import static org.mockito.Mockito.any; import static org.mockito.Mockito.any; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doAnswer; Loading @@ -28,10 +29,15 @@ import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothManager; import android.bluetooth.BluetoothUuid; import android.content.ContentValues; import android.content.ContentValues; import android.content.Context; import android.content.Context; import android.content.ContextWrapper; import android.content.ContextWrapper; import android.content.Intent; import android.content.IntentFilter; import android.content.IntentFilter; import android.net.Uri; import android.net.Uri; import android.os.Looper; import android.os.Looper; Loading @@ -51,7 +57,8 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.mockito.MockitoAnnotations; import org.mockito.Spy; import java.util.Objects; @MediumTest @MediumTest @RunWith(AndroidJUnit4.class) @RunWith(AndroidJUnit4.class) Loading @@ -72,8 +79,8 @@ public class BluetoothOppTransferTest { @Mock @Mock BluetoothOppObexSession mSession; BluetoothOppObexSession mSession; @Spy @Mock BluetoothMethodProxy mCallProxy = BluetoothMethodProxy.getInstance(); BluetoothMethodProxy mCallProxy; Context mContext; Context mContext; BluetoothOppBatch mBluetoothOppBatch; BluetoothOppBatch mBluetoothOppBatch; BluetoothOppTransfer mTransfer; BluetoothOppTransfer mTransfer; Loading Loading @@ -257,4 +264,84 @@ public class BluetoothOppTransferTest { verify(mContext).sendBroadcast(argThat( verify(mContext).sendBroadcast(argThat( arg -> arg.getAction().equals(BluetoothShare.USER_CONFIRMATION_TIMEOUT_ACTION))); arg -> arg.getAction().equals(BluetoothShare.USER_CONFIRMATION_TIMEOUT_ACTION))); } } @Test public void socketConnectThreadConstructors() { String address = "AA:BB:CC:EE:DD:11"; BluetoothDevice device = (mContext.getSystemService(BluetoothManager.class)) .getAdapter().getRemoteDevice(address); BluetoothOppTransfer transfer = new BluetoothOppTransfer(mContext, mBluetoothOppBatch); BluetoothOppTransfer.SocketConnectThread socketConnectThread = transfer.new SocketConnectThread(device, true); BluetoothOppTransfer.SocketConnectThread socketConnectThread2 = transfer.new SocketConnectThread(device, true, false, 0); assertThat(Objects.equals(socketConnectThread.mDevice, device)).isTrue(); assertThat(Objects.equals(socketConnectThread2.mDevice, device)).isTrue(); } @Test public void socketConnectThreadInterrupt() { String address = "AA:BB:CC:EE:DD:11"; BluetoothDevice device = (mContext.getSystemService(BluetoothManager.class)) .getAdapter().getRemoteDevice(address); BluetoothOppTransfer transfer = new BluetoothOppTransfer(mContext, mBluetoothOppBatch); BluetoothOppTransfer.SocketConnectThread socketConnectThread = transfer.new SocketConnectThread(device, true); socketConnectThread.interrupt(); assertThat(socketConnectThread.mIsInterrupted).isTrue(); } @Test @SuppressWarnings("DoNotCall") public void socketConnectThreadRun_bluetoothDisabled_connectionFailed() { String address = "AA:BB:CC:EE:DD:11"; BluetoothDevice device = (mContext.getSystemService(BluetoothManager.class)) .getAdapter().getRemoteDevice(address); BluetoothOppTransfer transfer = new BluetoothOppTransfer(mContext, mBluetoothOppBatch); BluetoothOppTransfer.SocketConnectThread socketConnectThread = transfer.new SocketConnectThread(device, true); transfer.mSessionHandler = mEventHandler; socketConnectThread.run(); verify(mCallProxy).handlerSendEmptyMessage(any(), eq(TRANSPORT_ERROR)); } @Test public void oppConnectionReceiver_onReceiveWithActionAclDisconnected_sendsConnectTimeout() { BluetoothDevice device = (mContext.getSystemService(BluetoothManager.class)) .getAdapter().getRemoteDevice(mDestination); BluetoothOppTransfer transfer = new BluetoothOppTransfer(mContext, mBluetoothOppBatch); transfer.mCurrentShare = mInitShareInfo; transfer.mCurrentShare.mConfirm = BluetoothShare.USER_CONFIRMATION_PENDING; BluetoothOppTransfer.OppConnectionReceiver receiver = transfer.new OppConnectionReceiver(); Intent intent = new Intent(); intent.setAction(BluetoothDevice.ACTION_ACL_DISCONNECTED); intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device); transfer.mSessionHandler = mEventHandler; receiver.onReceive(mContext, intent); verify(mCallProxy).handlerSendEmptyMessage(any(), eq(BluetoothOppObexSession.MSG_CONNECT_TIMEOUT)); } @Test public void oppConnectionReceiver_onReceiveWithActionSdpRecord_sendsNoMessage() { BluetoothDevice device = (mContext.getSystemService(BluetoothManager.class)) .getAdapter().getRemoteDevice(mDestination); BluetoothOppTransfer transfer = new BluetoothOppTransfer(mContext, mBluetoothOppBatch); transfer.mCurrentShare = mInitShareInfo; transfer.mCurrentShare.mConfirm = BluetoothShare.USER_CONFIRMATION_PENDING; transfer.mDevice = device; transfer.mSessionHandler = mEventHandler; BluetoothOppTransfer.OppConnectionReceiver receiver = transfer.new OppConnectionReceiver(); Intent intent = new Intent(); intent.setAction(BluetoothDevice.ACTION_SDP_RECORD); intent.putExtra(BluetoothDevice.EXTRA_UUID, BluetoothUuid.OBEX_OBJECT_PUSH); intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device); receiver.onReceive(mContext, intent); // bluetooth device name is null => skip without interaction verifyNoMoreInteractions(mCallProxy); } } } Loading
android/app/src/com/android/bluetooth/BluetoothMethodProxy.java +7 −0 Original line number Original line Diff line number Diff line Loading @@ -178,6 +178,13 @@ public class BluetoothMethodProxy { context.sendBroadcast(intent); context.sendBroadcast(intent); } } /** * Proxies {@link Handler#sendEmptyMessage(int)}}. */ public boolean handlerSendEmptyMessage(Handler handler, final int what) { return handler.sendEmptyMessage(what); } /** /** * Proxies {@link HeaderSet#getHeader}. * Proxies {@link HeaderSet#getHeader}. */ */ Loading
android/app/src/com/android/bluetooth/opp/BluetoothOppTransfer.java +23 −11 Original line number Original line Diff line number Diff line Loading @@ -92,23 +92,27 @@ public class BluetoothOppTransfer implements BluetoothOppBatch.BluetoothOppBatch private BluetoothAdapter mAdapter; private BluetoothAdapter mAdapter; private BluetoothDevice mDevice; @VisibleForTesting BluetoothDevice mDevice; private BluetoothOppBatch mBatch; private BluetoothOppBatch mBatch; private BluetoothOppObexSession mSession; private BluetoothOppObexSession mSession; private BluetoothOppShareInfo mCurrentShare; @VisibleForTesting BluetoothOppShareInfo mCurrentShare; private ObexTransport mTransport; private ObexTransport mTransport; private HandlerThread mHandlerThread; private HandlerThread mHandlerThread; private EventHandler mSessionHandler; @VisibleForTesting EventHandler mSessionHandler; private long mTimestamp; private long mTimestamp; private class OppConnectionReceiver extends BroadcastReceiver { @VisibleForTesting class OppConnectionReceiver extends BroadcastReceiver { @Override @Override public void onReceive(Context context, Intent intent) { public void onReceive(Context context, Intent intent) { String action = intent.getAction(); String action = intent.getAction(); Loading Loading @@ -139,8 +143,8 @@ public class BluetoothOppTransfer implements BluetoothOppBatch.BluetoothOppBatch // Remove the timeout message triggered earlier during Obex Put // Remove the timeout message triggered earlier during Obex Put mSessionHandler.removeMessages(BluetoothOppObexSession.MSG_CONNECT_TIMEOUT); mSessionHandler.removeMessages(BluetoothOppObexSession.MSG_CONNECT_TIMEOUT); // Now reuse the same message to clean up the session. // Now reuse the same message to clean up the session. mSessionHandler.sendMessage(mSessionHandler.obtainMessage( BluetoothMethodProxy.getInstance().handlerSendEmptyMessage(mSessionHandler, BluetoothOppObexSession.MSG_CONNECT_TIMEOUT)); BluetoothOppObexSession.MSG_CONNECT_TIMEOUT); } } } catch (Exception e) { } catch (Exception e) { e.printStackTrace(); e.printStackTrace(); Loading @@ -160,7 +164,11 @@ public class BluetoothOppTransfer implements BluetoothOppBatch.BluetoothOppBatch Log.w(TAG, "OPP SDP search, target device is null, ignoring result"); Log.w(TAG, "OPP SDP search, target device is null, ignoring result"); return; return; } } if (!device.getIdentityAddress().equalsIgnoreCase(mDevice.getIdentityAddress())) { String deviceIdentityAddress = device.getIdentityAddress(); String transferDeviceIdentityAddress = mDevice.getIdentityAddress(); if (deviceIdentityAddress == null || transferDeviceIdentityAddress == null || !deviceIdentityAddress.equalsIgnoreCase( transferDeviceIdentityAddress)) { Log.w(TAG, " OPP SDP search for wrong device, ignoring!!"); Log.w(TAG, " OPP SDP search for wrong device, ignoring!!"); return; return; } } Loading Loading @@ -676,10 +684,12 @@ public class BluetoothOppTransfer implements BluetoothOppBatch.BluetoothOppBatch @VisibleForTesting @VisibleForTesting SocketConnectThread mConnectThread; SocketConnectThread mConnectThread; private class SocketConnectThread extends Thread { @VisibleForTesting class SocketConnectThread extends Thread { private final String mHost; private final String mHost; private final BluetoothDevice mDevice; @VisibleForTesting final BluetoothDevice mDevice; private final int mChannel; private final int mChannel; Loading @@ -695,7 +705,8 @@ public class BluetoothOppTransfer implements BluetoothOppBatch.BluetoothOppBatch private boolean mSdpInitiated = false; private boolean mSdpInitiated = false; private boolean mIsInterrupted = false; @VisibleForTesting boolean mIsInterrupted = false; /* create a Rfcomm/L2CAP Socket */ /* create a Rfcomm/L2CAP Socket */ SocketConnectThread(BluetoothDevice device, boolean retry) { SocketConnectThread(BluetoothDevice device, boolean retry) { Loading Loading @@ -863,7 +874,8 @@ public class BluetoothOppTransfer implements BluetoothOppBatch.BluetoothOppBatch Log.e(TAG, "Error when close socket"); Log.e(TAG, "Error when close socket"); } } } } mSessionHandler.obtainMessage(TRANSPORT_ERROR).sendToTarget(); BluetoothMethodProxy.getInstance().handlerSendEmptyMessage(mSessionHandler, TRANSPORT_ERROR); return; return; } } Loading
android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppTransferTest.java +90 −3 Original line number Original line Diff line number Diff line Loading @@ -21,6 +21,7 @@ import static com.android.bluetooth.opp.BluetoothOppTransfer.TRANSPORT_ERROR; import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.nullable; import static org.mockito.ArgumentMatchers.nullable; import static org.mockito.Mockito.any; import static org.mockito.Mockito.any; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doAnswer; Loading @@ -28,10 +29,15 @@ import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothManager; import android.bluetooth.BluetoothUuid; import android.content.ContentValues; import android.content.ContentValues; import android.content.Context; import android.content.Context; import android.content.ContextWrapper; import android.content.ContextWrapper; import android.content.Intent; import android.content.IntentFilter; import android.content.IntentFilter; import android.net.Uri; import android.net.Uri; import android.os.Looper; import android.os.Looper; Loading @@ -51,7 +57,8 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.mockito.MockitoAnnotations; import org.mockito.Spy; import java.util.Objects; @MediumTest @MediumTest @RunWith(AndroidJUnit4.class) @RunWith(AndroidJUnit4.class) Loading @@ -72,8 +79,8 @@ public class BluetoothOppTransferTest { @Mock @Mock BluetoothOppObexSession mSession; BluetoothOppObexSession mSession; @Spy @Mock BluetoothMethodProxy mCallProxy = BluetoothMethodProxy.getInstance(); BluetoothMethodProxy mCallProxy; Context mContext; Context mContext; BluetoothOppBatch mBluetoothOppBatch; BluetoothOppBatch mBluetoothOppBatch; BluetoothOppTransfer mTransfer; BluetoothOppTransfer mTransfer; Loading Loading @@ -257,4 +264,84 @@ public class BluetoothOppTransferTest { verify(mContext).sendBroadcast(argThat( verify(mContext).sendBroadcast(argThat( arg -> arg.getAction().equals(BluetoothShare.USER_CONFIRMATION_TIMEOUT_ACTION))); arg -> arg.getAction().equals(BluetoothShare.USER_CONFIRMATION_TIMEOUT_ACTION))); } } @Test public void socketConnectThreadConstructors() { String address = "AA:BB:CC:EE:DD:11"; BluetoothDevice device = (mContext.getSystemService(BluetoothManager.class)) .getAdapter().getRemoteDevice(address); BluetoothOppTransfer transfer = new BluetoothOppTransfer(mContext, mBluetoothOppBatch); BluetoothOppTransfer.SocketConnectThread socketConnectThread = transfer.new SocketConnectThread(device, true); BluetoothOppTransfer.SocketConnectThread socketConnectThread2 = transfer.new SocketConnectThread(device, true, false, 0); assertThat(Objects.equals(socketConnectThread.mDevice, device)).isTrue(); assertThat(Objects.equals(socketConnectThread2.mDevice, device)).isTrue(); } @Test public void socketConnectThreadInterrupt() { String address = "AA:BB:CC:EE:DD:11"; BluetoothDevice device = (mContext.getSystemService(BluetoothManager.class)) .getAdapter().getRemoteDevice(address); BluetoothOppTransfer transfer = new BluetoothOppTransfer(mContext, mBluetoothOppBatch); BluetoothOppTransfer.SocketConnectThread socketConnectThread = transfer.new SocketConnectThread(device, true); socketConnectThread.interrupt(); assertThat(socketConnectThread.mIsInterrupted).isTrue(); } @Test @SuppressWarnings("DoNotCall") public void socketConnectThreadRun_bluetoothDisabled_connectionFailed() { String address = "AA:BB:CC:EE:DD:11"; BluetoothDevice device = (mContext.getSystemService(BluetoothManager.class)) .getAdapter().getRemoteDevice(address); BluetoothOppTransfer transfer = new BluetoothOppTransfer(mContext, mBluetoothOppBatch); BluetoothOppTransfer.SocketConnectThread socketConnectThread = transfer.new SocketConnectThread(device, true); transfer.mSessionHandler = mEventHandler; socketConnectThread.run(); verify(mCallProxy).handlerSendEmptyMessage(any(), eq(TRANSPORT_ERROR)); } @Test public void oppConnectionReceiver_onReceiveWithActionAclDisconnected_sendsConnectTimeout() { BluetoothDevice device = (mContext.getSystemService(BluetoothManager.class)) .getAdapter().getRemoteDevice(mDestination); BluetoothOppTransfer transfer = new BluetoothOppTransfer(mContext, mBluetoothOppBatch); transfer.mCurrentShare = mInitShareInfo; transfer.mCurrentShare.mConfirm = BluetoothShare.USER_CONFIRMATION_PENDING; BluetoothOppTransfer.OppConnectionReceiver receiver = transfer.new OppConnectionReceiver(); Intent intent = new Intent(); intent.setAction(BluetoothDevice.ACTION_ACL_DISCONNECTED); intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device); transfer.mSessionHandler = mEventHandler; receiver.onReceive(mContext, intent); verify(mCallProxy).handlerSendEmptyMessage(any(), eq(BluetoothOppObexSession.MSG_CONNECT_TIMEOUT)); } @Test public void oppConnectionReceiver_onReceiveWithActionSdpRecord_sendsNoMessage() { BluetoothDevice device = (mContext.getSystemService(BluetoothManager.class)) .getAdapter().getRemoteDevice(mDestination); BluetoothOppTransfer transfer = new BluetoothOppTransfer(mContext, mBluetoothOppBatch); transfer.mCurrentShare = mInitShareInfo; transfer.mCurrentShare.mConfirm = BluetoothShare.USER_CONFIRMATION_PENDING; transfer.mDevice = device; transfer.mSessionHandler = mEventHandler; BluetoothOppTransfer.OppConnectionReceiver receiver = transfer.new OppConnectionReceiver(); Intent intent = new Intent(); intent.setAction(BluetoothDevice.ACTION_SDP_RECORD); intent.putExtra(BluetoothDevice.EXTRA_UUID, BluetoothUuid.OBEX_OBJECT_PUSH); intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device); receiver.onReceive(mContext, intent); // bluetooth device name is null => skip without interaction verifyNoMoreInteractions(mCallProxy); } } }