PandoraServer: report full stacktrace through gRPC
Test: avatar run
Change-Id: I867aabb80a4f280563a15db181ce683a166c8819
diff --git a/android/pandora/server/src/com/android/pandora/A2dp.kt b/android/pandora/server/src/com/android/pandora/A2dp.kt
index cce3715..7e5f426 100644
--- a/android/pandora/server/src/com/android/pandora/A2dp.kt
+++ b/android/pandora/server/src/com/android/pandora/A2dp.kt
@@ -28,6 +28,8 @@
import io.grpc.Status
import io.grpc.stub.StreamObserver
import java.io.Closeable
+import java.io.PrintWriter
+import java.io.StringWriter
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.cancel
@@ -91,8 +93,7 @@
.first()
if (state == BluetoothProfile.STATE_DISCONNECTED) {
- Log.e(TAG, "openSource failed, A2DP has been disconnected")
- throw Status.UNKNOWN.asException()
+ throw RuntimeException("openSource failed, A2DP has been disconnected")
}
}
@@ -124,8 +125,7 @@
.first()
if (state == BluetoothProfile.STATE_DISCONNECTED) {
- Log.e(TAG, "waitSource failed, A2DP has been disconnected")
- throw Status.UNKNOWN.asException()
+ throw RuntimeException("waitSource failed, A2DP has been disconnected")
}
}
@@ -146,8 +146,7 @@
Log.i(TAG, "start: device=$device")
if (bluetoothA2dp.getConnectionState(device) != BluetoothA2dp.STATE_CONNECTED) {
- Log.e(TAG, "Device is not connected, cannot start")
- throw Status.UNKNOWN.asException()
+ throw RuntimeException("Device is not connected, cannot start")
}
audioTrack!!.play()
@@ -171,13 +170,11 @@
Log.i(TAG, "suspend: device=$device")
if (bluetoothA2dp.getConnectionState(device) != BluetoothA2dp.STATE_CONNECTED) {
- Log.e(TAG, "Device is not connected, cannot suspend")
- throw Status.UNKNOWN.asException()
+ throw RuntimeException("Device is not connected, cannot suspend")
}
if (!bluetoothA2dp.isA2dpPlaying(device)) {
- Log.e(TAG, "Device is already suspended, cannot suspend")
- throw Status.UNKNOWN.asException()
+ throw RuntimeException("Device is already suspended, cannot suspend")
}
val a2dpPlayingStateFlow =
@@ -201,8 +198,7 @@
Log.i(TAG, "isSuspended: device=$device")
if (bluetoothA2dp.getConnectionState(device) != BluetoothA2dp.STATE_CONNECTED) {
- Log.e(TAG, "Device is not connected, cannot get suspend state")
- throw Status.UNKNOWN.asException()
+ throw RuntimeException("Device is not connected, cannot get suspend state")
}
val isSuspended = bluetoothA2dp.isA2dpPlaying(device)
@@ -216,8 +212,7 @@
Log.i(TAG, "close: device=$device")
if (bluetoothA2dp.getConnectionState(device) != BluetoothA2dp.STATE_CONNECTED) {
- Log.e(TAG, "Device is not connected, cannot close")
- throw Status.UNKNOWN.asException()
+ throw RuntimeException("Device is not connected, cannot close")
}
val a2dpConnectionStateChangedFlow =
@@ -270,9 +265,13 @@
)
}
}
- override fun onError(t: Throwable?) {
- Log.e(TAG, t.toString())
- responseObserver.onError(t)
+ override fun onError(t: Throwable) {
+ t.printStackTrace()
+ val sw = StringWriter()
+ t.printStackTrace(PrintWriter(sw))
+ responseObserver.onError(
+ Status.UNKNOWN.withCause(t).withDescription(sw.toString()).asException()
+ )
}
override fun onCompleted() {
responseObserver.onNext(PlaybackAudioResponse.getDefaultInstance())
@@ -290,8 +289,7 @@
Log.i(TAG, "getAudioEncoding: device=$device")
if (bluetoothA2dp.getConnectionState(device) != BluetoothA2dp.STATE_CONNECTED) {
- Log.e(TAG, "Device is not connected, cannot getAudioEncoding")
- throw Status.UNKNOWN.asException()
+ throw RuntimeException("Device is not connected, cannot getAudioEncoding")
}
// For now, we only support 44100 kHz sampling rate.
diff --git a/android/pandora/server/src/com/android/pandora/A2dpSink.kt b/android/pandora/server/src/com/android/pandora/A2dpSink.kt
index 1b941f2..5785e7c 100644
--- a/android/pandora/server/src/com/android/pandora/A2dpSink.kt
+++ b/android/pandora/server/src/com/android/pandora/A2dpSink.kt
@@ -25,7 +25,6 @@
import android.content.IntentFilter
import android.media.*
import android.util.Log
-import io.grpc.Status
import io.grpc.stub.StreamObserver
import java.io.Closeable
import kotlinx.coroutines.CoroutineScope
@@ -85,8 +84,7 @@
.first()
if (state == BluetoothProfile.STATE_DISCONNECTED) {
- Log.e(TAG, "waitStream failed, A2DP has been disconnected")
- throw Status.UNKNOWN.asException()
+ throw RuntimeException("waitStream failed, A2DP has been disconnected")
}
}
@@ -100,8 +98,7 @@
val device = request.sink.connection.toBluetoothDevice(bluetoothAdapter)
Log.i(TAG, "close: device=$device")
if (bluetoothA2dpSink.getConnectionState(device) != BluetoothProfile.STATE_CONNECTED) {
- Log.e(TAG, "Device is not connected, cannot close")
- throw Status.UNKNOWN.asException()
+ throw RuntimeException("Device is not connected, cannot close")
}
val a2dpConnectionStateChangedFlow =
diff --git a/android/pandora/server/src/com/android/pandora/Gatt.kt b/android/pandora/server/src/com/android/pandora/Gatt.kt
index 60d7ba5..77b6c88 100644
--- a/android/pandora/server/src/com/android/pandora/Gatt.kt
+++ b/android/pandora/server/src/com/android/pandora/Gatt.kt
@@ -26,7 +26,6 @@
import android.content.Intent
import android.content.IntentFilter
import android.util.Log
-import io.grpc.Status
import io.grpc.stub.StreamObserver
import java.io.Closeable
import java.util.UUID
@@ -77,8 +76,7 @@
val mtu = request.mtu
Log.i(TAG, "exchangeMTU MTU=$mtu")
if (!GattInstance.get(request.connection.address).mGatt.requestMtu(mtu)) {
- Log.e(TAG, "Error on requesting MTU $mtu")
- throw Status.UNKNOWN.asException()
+ throw RuntimeException("Error on requesting MTU $mtu")
}
ExchangeMTUResponse.newBuilder().build()
}
@@ -383,8 +381,7 @@
private suspend fun tryDiscoverServices(gattInstance: GattInstance) {
if (!gattInstance.servicesDiscovered() && !gattInstance.mGatt.discoverServices()) {
- Log.e(TAG, "Error on discovering services for $gattInstance")
- throw Status.UNKNOWN.asException()
+ throw RuntimeException("Error on discovering services for $gattInstance")
} else {
gattInstance.waitForDiscoveryEnd()
}
diff --git a/android/pandora/server/src/com/android/pandora/GattInstance.kt b/android/pandora/server/src/com/android/pandora/GattInstance.kt
index edf5111..efc938e 100644
--- a/android/pandora/server/src/com/android/pandora/GattInstance.kt
+++ b/android/pandora/server/src/com/android/pandora/GattInstance.kt
@@ -56,11 +56,7 @@
) {}
private var mGattInstanceValuesRead = arrayListOf<GattInstanceValueRead>()
- class GattInstanceValueWrote(
- var uuid: UUID?,
- var handle: Int,
- var status: AttStatusCode
- ) {}
+ class GattInstanceValueWrote(var uuid: UUID?, var handle: Int, var status: AttStatusCode) {}
private var mGattInstanceValueWrote = GattInstanceValueWrote(null, 0, AttStatusCode.UNKNOWN_ERROR)
companion object GattManager {
@@ -320,7 +316,8 @@
characteristic.getInstanceId(),
AttStatusCode.UNKNOWN_ERROR
)
- if (mGatt.writeCharacteristic(
+ if (
+ mGatt.writeCharacteristic(
characteristic,
value,
BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT
@@ -329,7 +326,6 @@
waitForWriteEnd()
}
return mGattInstanceValueWrote
-
}
public suspend fun writeDescriptorBlocking(
@@ -341,15 +337,10 @@
descriptor.getInstanceId(),
AttStatusCode.UNKNOWN_ERROR
)
- if (mGatt.writeDescriptor(
- descriptor,
- value
- ) == BluetoothStatusCodes.SUCCESS
- ) {
+ if (mGatt.writeDescriptor(descriptor, value) == BluetoothStatusCodes.SUCCESS) {
waitForWriteEnd()
}
return mGattInstanceValueWrote
-
}
public fun disconnectInstance() {
diff --git a/android/pandora/server/src/com/android/pandora/GattServerManager.kt b/android/pandora/server/src/com/android/pandora/GattServerManager.kt
index 3a33d64..b6d3c52 100644
--- a/android/pandora/server/src/com/android/pandora/GattServerManager.kt
+++ b/android/pandora/server/src/com/android/pandora/GattServerManager.kt
@@ -68,7 +68,13 @@
ByteArray(negociatedMtu)
)
} else {
- server.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, offset, ByteArray(512 - offset))
+ server.sendResponse(
+ device,
+ requestId,
+ BluetoothGatt.GATT_SUCCESS,
+ offset,
+ ByteArray(512 - offset)
+ )
}
}
diff --git a/android/pandora/server/src/com/android/pandora/Host.kt b/android/pandora/server/src/com/android/pandora/Host.kt
index 389f19e..aaf7481 100644
--- a/android/pandora/server/src/com/android/pandora/Host.kt
+++ b/android/pandora/server/src/com/android/pandora/Host.kt
@@ -41,10 +41,10 @@
import android.util.Log
import com.google.protobuf.ByteString
import com.google.protobuf.Empty
-import io.grpc.Status
import io.grpc.stub.StreamObserver
-import java.nio.ByteBuffer
import java.io.Closeable
+import java.lang.IllegalArgumentException
+import java.nio.ByteBuffer
import java.time.Duration
import java.util.UUID
import kotlinx.coroutines.CoroutineScope
@@ -68,9 +68,8 @@
object ByteArrayOps {
public fun getUShortAt(input: ByteArray, index: Int): UShort {
- return (
- ((input[index + 1].toUInt() and 0xffU) shl 8) or
- (input[index].toUInt() and 0xffU)).toUShort()
+ return (((input[index + 1].toUInt() and 0xffU) shl 8) or (input[index].toUInt() and 0xffU))
+ .toUShort()
}
public fun getShortAt(input: ByteArray, index: Int): Short {
@@ -78,11 +77,10 @@
}
public fun getUIntAt(input: ByteArray, index: Int): UInt {
- return (
- ((input[index + 3].toUInt() and 0xffU) shl 24) or
+ return (((input[index + 3].toUInt() and 0xffU) shl 24) or
((input[index + 2].toUInt() and 0xffU) shl 16) or
((input[index + 1].toUInt() and 0xffU) shl 8) or
- (input[index].toUInt() and 0xffU))
+ (input[index].toUInt() and 0xffU))
}
public fun getIntAt(input: ByteArray, index: Int): Int {
@@ -90,10 +88,9 @@
}
public fun getUInt24At(input: ByteArray, index: Int): UInt {
- return (
- ((input[index + 2].toUInt() and 0xffU) shl 16) or
+ return (((input[index + 2].toUInt() and 0xffU) shl 16) or
((input[index + 1].toUInt() and 0xffU) shl 8) or
- (input[index].toUInt() and 0xffU))
+ (input[index].toUInt() and 0xffU))
}
public fun getInt24At(input: ByteArray, index: Int): Int {
@@ -280,14 +277,14 @@
responseObserver: StreamObserver<WaitConnectionResponse>
) {
grpcUnary(scope, responseObserver) {
- if (request.address.isEmpty()) throw Status.UNKNOWN.asException()
+ if (request.address.isEmpty())
+ throw IllegalArgumentException("Request address field must be set")
var bluetoothDevice = request.address.toBluetoothDevice(bluetoothAdapter)
Log.i(TAG, "waitConnection: device=$bluetoothDevice")
if (!bluetoothAdapter.isEnabled) {
- Log.e(TAG, "Bluetooth is not enabled, cannot waitConnection")
- throw Status.UNKNOWN.asException()
+ throw RuntimeException("Bluetooth is not enabled, cannot waitConnection")
}
if (!bluetoothDevice.isConnected() || waitedAclConnection.contains(bluetoothDevice)) {
@@ -312,8 +309,7 @@
val bluetoothDevice = request.connection.toBluetoothDevice(bluetoothAdapter)
Log.i(TAG, "waitDisconnection: device=$bluetoothDevice")
if (!bluetoothAdapter.isEnabled) {
- Log.e(TAG, "Bluetooth is not enabled, cannot waitDisconnection")
- throw Status.UNKNOWN.asException()
+ throw RuntimeException("Bluetooth is not enabled, cannot waitDisconnection")
}
if (bluetoothDevice.bondState != BluetoothDevice.BOND_NONE) {
flow
@@ -327,6 +323,8 @@
override fun connect(request: ConnectRequest, responseObserver: StreamObserver<ConnectResponse>) {
grpcUnary(scope, responseObserver) {
+ if (request.address.isEmpty())
+ throw IllegalArgumentException("Request address field must be set")
val bluetoothDevice = request.address.toBluetoothDevice(bluetoothAdapter)
Log.i(TAG, "connect: address=$bluetoothDevice")
@@ -360,8 +358,7 @@
Log.i(TAG, "disconnect: device=$bluetoothDevice")
if (!bluetoothDevice.isConnected()) {
- Log.e(TAG, "Device is not connected, cannot disconnect")
- throw Status.UNKNOWN.asException()
+ throw RuntimeException("Device is not connected, cannot disconnect")
}
when (request.connection.transport) {
@@ -381,16 +378,14 @@
instance
}
if (gattInstance.isDisconnected()) {
- Log.e(TAG, "Device is not connected, cannot disconnect")
- throw Status.UNKNOWN.asException()
+ throw RuntimeException("Device is not connected, cannot disconnect")
}
bluetoothDevice.disconnect()
gattInstance.disconnectInstance()
}
else -> {
- Log.e(TAG, "Device type UNKNOWN")
- throw Status.UNKNOWN.asException()
+ throw RuntimeException("Device type UNKNOWN")
}
}
flow
@@ -412,8 +407,7 @@
ownAddressType != OwnAddressType.RANDOM &&
ownAddressType != OwnAddressType.RESOLVABLE_OR_RANDOM
) {
- Log.e(TAG, "connectLE: Unsupported OwnAddressType: $ownAddressType")
- throw Status.UNKNOWN.asException()
+ throw RuntimeException("connectLE: Unsupported OwnAddressType: $ownAddressType")
}
val (address, type) =
when (request.getAddressCase()!!) {
@@ -425,7 +419,8 @@
Pair(request.publicIdentity, BluetoothDevice.ADDRESS_TYPE_PUBLIC)
ConnectLERequest.AddressCase.RANDOM_STATIC_IDENTITY ->
Pair(request.randomStaticIdentity, BluetoothDevice.ADDRESS_TYPE_RANDOM)
- ConnectLERequest.AddressCase.ADDRESS_NOT_SET -> throw Status.UNKNOWN.asException()
+ ConnectLERequest.AddressCase.ADDRESS_NOT_SET ->
+ throw IllegalArgumentException("Request address field must be set")
}
Log.i(TAG, "connectLE: $address")
val bluetoothDevice = scanLeDevice(address.decodeAsMacAddressToString(), type)!!
@@ -493,8 +488,7 @@
!dataTypesRequest.getIncompleteServiceClassUuids32List().isEmpty() or
!dataTypesRequest.getIncompleteServiceClassUuids128List().isEmpty()
) {
- Log.e(TAG, "Incomplete Service Class Uuids not supported")
- throw Status.UNKNOWN.asException()
+ throw RuntimeException("Incomplete Service Class Uuids not supported")
}
// Handle service uuids
@@ -600,43 +594,47 @@
var dataTypesBuilder =
DataTypes.newBuilder().setTxPowerLevel(scanRecord.getTxPowerLevel())
- scanData[ScanRecord.DATA_TYPE_LOCAL_NAME_SHORT]?.let {
+ scanData[ScanRecord.DATA_TYPE_LOCAL_NAME_SHORT]?.let {
dataTypesBuilder.setShortenedLocalName(it.decodeToString())
}
?: run { dataTypesBuilder.setIncludeShortenedLocalName(false) }
- scanData[ScanRecord.DATA_TYPE_LOCAL_NAME_COMPLETE]?.let {
+ scanData[ScanRecord.DATA_TYPE_LOCAL_NAME_COMPLETE]?.let {
dataTypesBuilder.setCompleteLocalName(it.decodeToString())
}
?: run { dataTypesBuilder.setIncludeCompleteLocalName(false) }
- scanData[ScanRecord.DATA_TYPE_ADVERTISING_INTERVAL]?.let {
+ scanData[ScanRecord.DATA_TYPE_ADVERTISING_INTERVAL]?.let {
dataTypesBuilder.setAdvertisingInterval(ByteArrayOps.getShortAt(it, 0).toInt())
}
- scanData[ScanRecord.DATA_TYPE_ADVERTISING_INTERVAL_LONG]?.let {
+ scanData[ScanRecord.DATA_TYPE_ADVERTISING_INTERVAL_LONG]?.let {
dataTypesBuilder.setAdvertisingInterval(ByteArrayOps.getIntAt(it, 0))
}
- scanData[ScanRecord.DATA_TYPE_APPEARANCE]?.let {
+ scanData[ScanRecord.DATA_TYPE_APPEARANCE]?.let {
dataTypesBuilder.setAppearance(ByteArrayOps.getShortAt(it, 0).toInt())
}
- scanData[ScanRecord.DATA_TYPE_CLASS_OF_DEVICE]?.let {
+ scanData[ScanRecord.DATA_TYPE_CLASS_OF_DEVICE]?.let {
dataTypesBuilder.setClassOfDevice(ByteArrayOps.getInt24At(it, 0))
}
- scanData[ScanRecord.DATA_TYPE_URI]?.let {
+ scanData[ScanRecord.DATA_TYPE_URI]?.let {
dataTypesBuilder.setUri(it.decodeToString())
}
- scanData[ScanRecord.DATA_TYPE_LE_SUPPORTED_FEATURES]?.let {
+ scanData[ScanRecord.DATA_TYPE_LE_SUPPORTED_FEATURES]?.let {
dataTypesBuilder.setLeSupportedFeatures(ByteString.copyFrom(it))
}
- scanData[ScanRecord.DATA_TYPE_SLAVE_CONNECTION_INTERVAL_RANGE]?.let {
- dataTypesBuilder.setPeripheralConnectionIntervalMin(ByteArrayOps.getShortAt(it, 0).toInt())
- dataTypesBuilder.setPeripheralConnectionIntervalMax(ByteArrayOps.getShortAt(it, 2).toInt())
+ scanData[ScanRecord.DATA_TYPE_SLAVE_CONNECTION_INTERVAL_RANGE]?.let {
+ dataTypesBuilder.setPeripheralConnectionIntervalMin(
+ ByteArrayOps.getShortAt(it, 0).toInt()
+ )
+ dataTypesBuilder.setPeripheralConnectionIntervalMax(
+ ByteArrayOps.getShortAt(it, 2).toInt()
+ )
}
for (serviceDataEntry in serviceData) {
@@ -711,8 +709,7 @@
.put(manufacturerSpecificDatas.get(id))
}
dataTypesBuilder.setManufacturerSpecificData(
- ByteString.copyFrom(manufacturerData.array(), 0,
- manufacturerData.position())
+ ByteString.copyFrom(manufacturerData.array(), 0, manufacturerData.position())
)
val primaryPhy =
when (result.getPrimaryPhy()) {
diff --git a/android/pandora/server/src/com/android/pandora/Main.kt b/android/pandora/server/src/com/android/pandora/Main.kt
index 5f34a12..9881d1b 100644
--- a/android/pandora/server/src/com/android/pandora/Main.kt
+++ b/android/pandora/server/src/com/android/pandora/Main.kt
@@ -20,8 +20,8 @@
import android.os.Bundle
import android.os.Debug
import android.util.Log
-import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.core.app.ApplicationProvider.getApplicationContext
+import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.runner.MonitoringInstrumentation
@kotlinx.coroutines.ExperimentalCoroutinesApi
diff --git a/android/pandora/server/src/com/android/pandora/MediaPlayerBrowserService.kt b/android/pandora/server/src/com/android/pandora/MediaPlayerBrowserService.kt
index 8ba4618..d64aea1 100644
--- a/android/pandora/server/src/com/android/pandora/MediaPlayerBrowserService.kt
+++ b/android/pandora/server/src/com/android/pandora/MediaPlayerBrowserService.kt
@@ -79,7 +79,8 @@
}
fun play() {
- if (currentTrack == -1 || currentTrack == QUEUE_SIZE) currentTrack = QUEUE_START_INDEX else currentTrack += 1
+ if (currentTrack == -1 || currentTrack == QUEUE_SIZE) currentTrack = QUEUE_START_INDEX
+ else currentTrack += 1
setPlaybackState(PlaybackState.STATE_PLAYING)
mediaSession.setMetadata(metadataItems.get("" + currentTrack))
}
@@ -102,14 +103,16 @@
}
fun forward() {
- if (currentTrack == QUEUE_SIZE || currentTrack == -1) currentTrack = QUEUE_START_INDEX else currentTrack += 1
+ if (currentTrack == QUEUE_SIZE || currentTrack == -1) currentTrack = QUEUE_START_INDEX
+ else currentTrack += 1
setPlaybackState(PlaybackState.STATE_SKIPPING_TO_NEXT)
mediaSession.setMetadata(metadataItems.get("" + currentTrack))
setPlaybackState(PlaybackState.STATE_PLAYING)
}
fun backward() {
- if (currentTrack == QUEUE_START_INDEX || currentTrack == -1) currentTrack = QUEUE_SIZE else currentTrack -= 1
+ if (currentTrack == QUEUE_START_INDEX || currentTrack == -1) currentTrack = QUEUE_SIZE
+ else currentTrack -= 1
setPlaybackState(PlaybackState.STATE_SKIPPING_TO_PREVIOUS)
mediaSession.setMetadata(metadataItems.get("" + currentTrack))
setPlaybackState(PlaybackState.STATE_PLAYING)
@@ -190,8 +193,14 @@
MediaMetadata.Builder()
.putString(MediaMetadata.METADATA_KEY_MEDIA_ID, NOW_PLAYING_PREFIX + item)
.putString(MediaMetadata.METADATA_KEY_TITLE, "Title$item")
- .putString(MediaMetadata.METADATA_KEY_ARTIST, if (item != QUEUE_SIZE) "Artist$item" else generateAlphanumericString(512))
- .putString(MediaMetadata.METADATA_KEY_ALBUM, if (item != QUEUE_SIZE) "Album$item" else generateAlphanumericString(512))
+ .putString(
+ MediaMetadata.METADATA_KEY_ARTIST,
+ if (item != QUEUE_SIZE) "Artist$item" else generateAlphanumericString(512)
+ )
+ .putString(
+ MediaMetadata.METADATA_KEY_ALBUM,
+ if (item != QUEUE_SIZE) "Album$item" else generateAlphanumericString(512)
+ )
.putLong(MediaMetadata.METADATA_KEY_TRACK_NUMBER, item.toLong())
.putLong(MediaMetadata.METADATA_KEY_NUM_TRACKS, QUEUE_SIZE.toLong())
.build()
@@ -252,6 +261,6 @@
const val QUEUE_SIZE = 6
const val NEW_QUEUE_ITEM_INDEX = 7
- fun isInitialized() : Boolean = this::instance.isInitialized
+ fun isInitialized(): Boolean = this::instance.isInitialized
}
}
diff --git a/android/pandora/server/src/com/android/pandora/Pbap.kt b/android/pandora/server/src/com/android/pandora/Pbap.kt
index 279d6f0..2ae7729 100644
--- a/android/pandora/server/src/com/android/pandora/Pbap.kt
+++ b/android/pandora/server/src/com/android/pandora/Pbap.kt
@@ -61,7 +61,7 @@
if (cursor.getCount() >= CONTACT_LIST_SIZE) return // return if contacts are present
- for (item in cursor.getCount()+1..CONTACT_LIST_SIZE) {
+ for (item in cursor.getCount() + 1..CONTACT_LIST_SIZE) {
addContact(item)
}
}
diff --git a/android/pandora/server/src/com/android/pandora/Security.kt b/android/pandora/server/src/com/android/pandora/Security.kt
index a3494e3..9fdc22e 100644
--- a/android/pandora/server/src/com/android/pandora/Security.kt
+++ b/android/pandora/server/src/com/android/pandora/Security.kt
@@ -34,7 +34,6 @@
import android.util.Log
import com.google.protobuf.ByteString
import com.google.protobuf.Empty
-import io.grpc.Status
import io.grpc.stub.StreamObserver
import java.io.Closeable
import kotlinx.coroutines.CoroutineScope
@@ -119,7 +118,8 @@
check(request.getLevelCase() == SecureRequest.LevelCase.LE)
val level = request.le
if (level == LE_LEVEL1) true
- else if (level == LE_LEVEL4) throw Status.UNKNOWN.asException()
+ else if (level == LE_LEVEL4)
+ throw RuntimeException("secure: Low-energy level 4 not supported")
else {
bluetoothDevice.createBond(transport)
waitLESecurityLevel(bluetoothDevice, level)
@@ -129,13 +129,14 @@
check(request.getLevelCase() == SecureRequest.LevelCase.CLASSIC)
val level = request.classic
if (level == LEVEL0) true
- else if (level >= LEVEL3) throw Status.UNKNOWN.asException()
+ else if (level >= LEVEL3)
+ throw RuntimeException("secure: Classic level up to 3 not supported")
else {
bluetoothDevice.createBond(transport)
waitBREDRSecurityLevel(bluetoothDevice, level)
}
}
- else -> throw Status.UNKNOWN.asException()
+ else -> throw RuntimeException("secure: Invalid transport")
}
val secureResponseBuilder = SecureResponse.newBuilder()
if (reached) secureResponseBuilder.setSuccess(Empty.getDefaultInstance())
@@ -159,7 +160,7 @@
Log.i(TAG, "waitBREDRSecurityLevel")
return when (level) {
LEVEL0 -> true
- LEVEL3 -> throw Status.UNKNOWN.asException()
+ LEVEL3 -> throw RuntimeException("waitSecurity: Classic level 3 not supported")
else -> {
val bondState = waitBondIntent(bluetoothDevice)
val isEncrypted = bluetoothDevice.isEncrypted()
@@ -179,14 +180,14 @@
Log.i(TAG, "waitLESecurityLevel")
return when (level) {
LE_LEVEL1 -> true
- LE_LEVEL4 -> throw Status.UNKNOWN.asException()
+ LE_LEVEL4 -> throw RuntimeException("waitSecurity: Low-energy level 4 not supported")
else -> {
val bondState = waitBondIntent(bluetoothDevice)
val isEncrypted = bluetoothDevice.isEncrypted()
when (level) {
LE_LEVEL2 -> isEncrypted
LE_LEVEL3 -> isEncrypted && bondState == BOND_BONDED
- else -> throw Status.UNKNOWN.asException()
+ else -> throw RuntimeException("waitSecurity: Low-energy level 4 not supported")
}
}
}
@@ -210,7 +211,7 @@
check(request.hasClassic())
waitBREDRSecurityLevel(bluetoothDevice, request.classic)
}
- else -> throw Status.UNKNOWN.asException()
+ else -> throw RuntimeException("secure: Invalid transport")
}
val waitSecurityBuilder = WaitSecurityResponse.newBuilder()
if (reached) waitSecurityBuilder.setSuccess(Empty.getDefaultInstance())
diff --git a/android/pandora/server/src/com/android/pandora/SecurityStorage.kt b/android/pandora/server/src/com/android/pandora/SecurityStorage.kt
index 8870e6c..f1e7f4a 100644
--- a/android/pandora/server/src/com/android/pandora/SecurityStorage.kt
+++ b/android/pandora/server/src/com/android/pandora/SecurityStorage.kt
@@ -18,7 +18,6 @@
import android.bluetooth.BluetoothAdapter
import android.bluetooth.BluetoothDevice
-import android.bluetooth.BluetoothDevice.BOND_BONDED
import android.bluetooth.BluetoothDevice.BOND_NONE
import android.bluetooth.BluetoothManager
import android.content.Context
@@ -69,13 +68,11 @@
grpcUnary(globalScope, responseObserver) {
val bondedDevices = bluetoothAdapter.getBondedDevices()
val bondedDevice =
- when(request.getAddressCase()!!) {
- IsBondedRequest.AddressCase.PUBLIC -> bondedDevices.firstOrNull {
- it.toByteString() == request.public
- }
- IsBondedRequest.AddressCase.RANDOM -> bondedDevices.firstOrNull {
- it.toByteString() == request.random
- }
+ when (request.getAddressCase()!!) {
+ IsBondedRequest.AddressCase.PUBLIC ->
+ bondedDevices.firstOrNull { it.toByteString() == request.public }
+ IsBondedRequest.AddressCase.RANDOM ->
+ bondedDevices.firstOrNull { it.toByteString() == request.random }
IsBondedRequest.AddressCase.ADDRESS_NOT_SET -> throw Status.UNKNOWN.asException()
}
Log.i(TAG, "isBonded: device=$bondedDevice")
diff --git a/android/pandora/server/src/com/android/pandora/Utils.kt b/android/pandora/server/src/com/android/pandora/Utils.kt
index 877f000..0aa6dd6 100644
--- a/android/pandora/server/src/com/android/pandora/Utils.kt
+++ b/android/pandora/server/src/com/android/pandora/Utils.kt
@@ -27,15 +27,17 @@
import android.media.*
import android.net.MacAddress
import android.os.ParcelFileDescriptor
-import android.os.ParcelUuid
import android.util.Log
import androidx.test.platform.app.InstrumentationRegistry
import com.google.protobuf.Any
import com.google.protobuf.ByteString
+import io.grpc.Status
import io.grpc.stub.ServerCallStreamObserver
import io.grpc.stub.StreamObserver
import java.io.BufferedReader
import java.io.InputStreamReader
+import java.io.PrintWriter
+import java.io.StringWriter
import java.util.concurrent.CancellationException
import java.util.stream.Collectors
import kotlinx.coroutines.CoroutineScope
@@ -103,7 +105,7 @@
* @param scope coroutine scope used to run the coroutine.
* @param responseObserver the gRPC stream observer on which to send the response.
* @param timeout the duration in seconds after which the coroutine is automatically cancelled and
- * returns a timeout error. Default: 60s.
+ * returns a timeout error. Default: 60s.
* @param block the suspended function to execute to get the response.
* @return reference to the coroutine as a Job.
*
@@ -133,7 +135,11 @@
responseObserver.onCompleted()
} catch (e: Throwable) {
e.printStackTrace()
- responseObserver.onError(e)
+ val sw = StringWriter()
+ e.printStackTrace(PrintWriter(sw))
+ responseObserver.onError(
+ Status.UNKNOWN.withCause(e).withDescription(sw.toString()).asException()
+ )
}
}
}
@@ -181,7 +187,11 @@
}
.catch {
it.printStackTrace()
- responseObserver.onError(it)
+ val sw = StringWriter()
+ it.printStackTrace(PrintWriter(sw))
+ responseObserver.onError(
+ Status.UNKNOWN.withCause(it).withDescription(sw.toString()).asException()
+ )
}
.launchIn(this)
}
@@ -208,6 +218,11 @@
override fun onError(e: Throwable) {
job.cancel()
e.printStackTrace()
+ val sw = StringWriter()
+ e.printStackTrace(PrintWriter(sw))
+ responseObserver.onError(
+ Status.UNKNOWN.withCause(e).withDescription(sw.toString()).asException()
+ )
}
}
}
@@ -254,7 +269,11 @@
}
.catch {
it.printStackTrace()
- responseObserver.onError(it)
+ val sw = StringWriter()
+ it.printStackTrace(PrintWriter(sw))
+ responseObserver.onError(
+ Status.UNKNOWN.withCause(it).withDescription(sw.toString()).asException()
+ )
}
.launchIn(this)
}