Loading android/pandora/server/src/com/android/pandora/A2dp.kt +3 −2 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ import android.media.* import android.util.Log import io.grpc.Status import io.grpc.stub.StreamObserver import java.io.Closeable import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.cancel Loading @@ -41,7 +42,7 @@ import pandora.A2DPGrpc.A2DPImplBase import pandora.A2dpProto.* @kotlinx.coroutines.ExperimentalCoroutinesApi class A2dp(val context: Context) : A2DPImplBase() { class A2dp(val context: Context) : A2DPImplBase(), Closeable { private val TAG = "PandoraA2dp" private val scope: CoroutineScope Loading @@ -64,7 +65,7 @@ class A2dp(val context: Context) : A2DPImplBase() { flow = intentFlow(context, intentFilter).shareIn(scope, SharingStarted.Eagerly) } fun deinit() { override fun close() { bluetoothAdapter.closeProfileProxy(BluetoothProfile.A2DP, bluetoothA2dp) scope.cancel() } Loading android/pandora/server/src/com/android/pandora/A2dpSink.kt +3 −2 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ import android.media.* import android.util.Log import io.grpc.Status import io.grpc.stub.StreamObserver import java.io.Closeable import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.cancel Loading @@ -40,7 +41,7 @@ import pandora.A2DPGrpc.A2DPImplBase import pandora.A2dpProto.* @kotlinx.coroutines.ExperimentalCoroutinesApi class A2dpSink(val context: Context) : A2DPImplBase() { class A2dpSink(val context: Context) : A2DPImplBase(), Closeable { private val TAG = "PandoraA2dpSink" private val scope: CoroutineScope Loading @@ -59,7 +60,7 @@ class A2dpSink(val context: Context) : A2DPImplBase() { flow = intentFlow(context, intentFilter).shareIn(scope, SharingStarted.Eagerly) } fun deinit() { override fun close() { bluetoothAdapter.closeProfileProxy(BluetoothProfile.A2DP_SINK, bluetoothA2dpSink) scope.cancel() } Loading android/pandora/server/src/com/android/pandora/AndroidInternal.kt +61 −33 Original line number Diff line number Diff line Loading @@ -16,34 +16,33 @@ package com.android.pandora import android.util.Log import android.bluetooth.BluetoothDevice import android.bluetooth.BluetoothManager import android.content.ComponentName import android.content.ContentUris import android.content.Context import com.google.protobuf.Empty import io.grpc.stub.StreamObserver import android.content.Intent import android.graphics.Bitmap import android.os.Environment import android.provider.MediaStore.Images.Media import android.provider.MediaStore.MediaColumns import android.provider.Telephony.* import android.telephony.SmsManager import android.telephony.SubscriptionManager import android.telephony.TelephonyManager import android.content.Intent import android.content.ComponentName import android.content.ContentUris import java.io.File import java.io.FileOutputStream import android.provider.MediaStore.Images.Media import android.provider.MediaStore.MediaColumns import android.net.Uri import kotlinx.coroutines.async import android.bluetooth.BluetoothAdapter import android.bluetooth.BluetoothDevice import android.bluetooth.BluetoothManager import android.util.Log import androidx.test.InstrumentationRegistry import androidx.test.uiautomator.By import androidx.test.uiautomator.UiDevice import androidx.test.uiautomator.Until import com.google.protobuf.Empty import io.grpc.stub.StreamObserver import java.io.Closeable import java.io.File import java.io.FileOutputStream import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.async import kotlinx.coroutines.cancel import pandora.AndroidGrpc.AndroidImplBase import pandora.AndroidProto.* Loading @@ -51,7 +50,7 @@ import pandora.AndroidProto.* private const val TAG = "PandoraAndroidInternal" @kotlinx.coroutines.ExperimentalCoroutinesApi class AndroidInternal(val context: Context) : AndroidImplBase() { class AndroidInternal(val context: Context) : AndroidImplBase(), Closeable { private val scope: CoroutineScope = CoroutineScope(Dispatchers.Default) private val INCOMING_FILE_ACCEPT_BTN = "ACCEPT" Loading @@ -73,10 +72,14 @@ class AndroidInternal(val context: Context) : AndroidImplBase() { createImageFile() } fun deinit() { override fun close() { scope.cancel() val file = File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), IMAGE_FILE_NAME) val file = File( Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), IMAGE_FILE_NAME ) if (file.exists()) { file.delete() Loading @@ -90,13 +93,19 @@ class AndroidInternal(val context: Context) : AndroidImplBase() { } } override fun setAccessPermission(request: SetAccessPermissionRequest, responseObserver: StreamObserver<Empty>) { override fun setAccessPermission( request: SetAccessPermissionRequest, responseObserver: StreamObserver<Empty> ) { grpcUnary<Empty>(scope, responseObserver) { val bluetoothDevice = request.address.toBluetoothDevice(bluetoothAdapter) when (request.accessType!!) { AccessType.ACCESS_MESSAGE -> bluetoothDevice.setMessageAccessPermission(BluetoothDevice.ACCESS_ALLOWED) AccessType.ACCESS_PHONEBOOK -> bluetoothDevice.setPhonebookAccessPermission(BluetoothDevice.ACCESS_ALLOWED) AccessType.ACCESS_SIM -> bluetoothDevice.setSimAccessPermission(BluetoothDevice.ACCESS_ALLOWED) AccessType.ACCESS_MESSAGE -> bluetoothDevice.setMessageAccessPermission(BluetoothDevice.ACCESS_ALLOWED) AccessType.ACCESS_PHONEBOOK -> bluetoothDevice.setPhonebookAccessPermission(BluetoothDevice.ACCESS_ALLOWED) AccessType.ACCESS_SIM -> bluetoothDevice.setSimAccessPermission(BluetoothDevice.ACCESS_ALLOWED) else -> {} } Empty.getDefaultInstance() Loading @@ -110,15 +119,25 @@ class AndroidInternal(val context: Context) : AndroidImplBase() { telephonyManager = telephonyManager.createForSubscriptionId(defaultSmsSub) val avdPhoneNumber = telephonyManager.getLine1Number() smsManager.sendTextMessage(avdPhoneNumber, avdPhoneNumber, generateAlphanumericString(DEFAULT_MESSAGE_LEN), null, null) smsManager.sendTextMessage( avdPhoneNumber, avdPhoneNumber, generateAlphanumericString(DEFAULT_MESSAGE_LEN), null, null ) Empty.getDefaultInstance() } } override fun acceptIncomingFile(request: Empty, responseObserver: StreamObserver<Empty>) { grpcUnary<Empty>(scope, responseObserver) { device.wait(Until.findObject(By.text(INCOMING_FILE_TITLE)), INCOMING_FILE_WAIT_TIMEOUT).click() device.wait(Until.findObject(By.text(INCOMING_FILE_ACCEPT_BTN)), INCOMING_FILE_WAIT_TIMEOUT).click() device .wait(Until.findObject(By.text(INCOMING_FILE_TITLE)), INCOMING_FILE_WAIT_TIMEOUT) .click() device .wait(Until.findObject(By.text(INCOMING_FILE_ACCEPT_BTN)), INCOMING_FILE_WAIT_TIMEOUT) .click() Empty.getDefaultInstance() } } Loading @@ -132,8 +151,11 @@ class AndroidInternal(val context: Context) : AndroidImplBase() { } suspend private fun waitAndSelectBluetoothDevice() { var selectJob = scope.async { device.wait(Until.findObject(By.textContains("Cuttlefish")), BT_DEVICE_SELECT_WAIT_TIMEOUT).click() var selectJob = scope.async { device .wait(Until.findObject(By.textContains("Cuttlefish")), BT_DEVICE_SELECT_WAIT_TIMEOUT) .click() } selectJob.await() } Loading @@ -148,14 +170,16 @@ class AndroidInternal(val context: Context) : AndroidImplBase() { sendingIntent.setComponent(ComponentName(BT_PKG_NAME, BT_OPP_LAUNCHER_ACTIVITY)) sendingIntent.putExtra(Intent.EXTRA_STREAM, contentUri) context.startActivity(sendingIntent) } catch(e: Exception) { } } catch (e: Exception) {} } private fun getImageId(fileName: String): Long { val selection = MediaColumns.DISPLAY_NAME + "=?" val selectionArgs = arrayOf(fileName) val cursor = context.getContentResolver().query(Media.EXTERNAL_CONTENT_URI, null, selection, selectionArgs, null) val cursor = context .getContentResolver() .query(Media.EXTERNAL_CONTENT_URI, null, selection, selectionArgs, null) cursor?.use { it.let { Loading @@ -168,7 +192,11 @@ class AndroidInternal(val context: Context) : AndroidImplBase() { private fun createImageFile() { val bitmapImage = Bitmap.createBitmap(30, 20, Bitmap.Config.ARGB_8888) val file = File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), IMAGE_FILE_NAME) val file = File( Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), IMAGE_FILE_NAME ) var fileOutputStream: FileOutputStream? = null if (file.exists()) { Loading android/pandora/server/src/com/android/pandora/Avrcp.kt +3 −2 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package com.android.pandora import android.bluetooth.BluetoothManager import android.content.Context import java.io.Closeable import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.cancel Loading @@ -25,7 +26,7 @@ import pandora.AVRCPGrpc.AVRCPImplBase import pandora.AvrcpProto.* @kotlinx.coroutines.ExperimentalCoroutinesApi class Avrcp(val context: Context) : AVRCPImplBase() { class Avrcp(val context: Context) : AVRCPImplBase(), Closeable { private val TAG = "PandoraAvrcp" private val scope: CoroutineScope Loading @@ -39,7 +40,7 @@ class Avrcp(val context: Context) : AVRCPImplBase() { scope = CoroutineScope(Dispatchers.Default) } fun deinit() { override fun close() { // Deinit the CoroutineScope scope.cancel() } Loading android/pandora/server/src/com/android/pandora/Gatt.kt +3 −2 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ 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 import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers Loading @@ -45,7 +46,7 @@ import pandora.GATTGrpc.GATTImplBase import pandora.GattProto.* @kotlinx.coroutines.ExperimentalCoroutinesApi class Gatt(private val context: Context) : GATTImplBase() { class Gatt(private val context: Context) : GATTImplBase(), Closeable { private val TAG = "PandoraGatt" private val mScope: CoroutineScope = CoroutineScope(Dispatchers.Default) Loading @@ -63,7 +64,7 @@ class Gatt(private val context: Context) : GATTImplBase() { flow = intentFlow(context, intentFilter).shareIn(mScope, SharingStarted.Eagerly) } fun deinit() { override fun close() { serverManager.server.close() mScope.cancel() } Loading Loading
android/pandora/server/src/com/android/pandora/A2dp.kt +3 −2 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ import android.media.* import android.util.Log import io.grpc.Status import io.grpc.stub.StreamObserver import java.io.Closeable import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.cancel Loading @@ -41,7 +42,7 @@ import pandora.A2DPGrpc.A2DPImplBase import pandora.A2dpProto.* @kotlinx.coroutines.ExperimentalCoroutinesApi class A2dp(val context: Context) : A2DPImplBase() { class A2dp(val context: Context) : A2DPImplBase(), Closeable { private val TAG = "PandoraA2dp" private val scope: CoroutineScope Loading @@ -64,7 +65,7 @@ class A2dp(val context: Context) : A2DPImplBase() { flow = intentFlow(context, intentFilter).shareIn(scope, SharingStarted.Eagerly) } fun deinit() { override fun close() { bluetoothAdapter.closeProfileProxy(BluetoothProfile.A2DP, bluetoothA2dp) scope.cancel() } Loading
android/pandora/server/src/com/android/pandora/A2dpSink.kt +3 −2 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ import android.media.* import android.util.Log import io.grpc.Status import io.grpc.stub.StreamObserver import java.io.Closeable import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.cancel Loading @@ -40,7 +41,7 @@ import pandora.A2DPGrpc.A2DPImplBase import pandora.A2dpProto.* @kotlinx.coroutines.ExperimentalCoroutinesApi class A2dpSink(val context: Context) : A2DPImplBase() { class A2dpSink(val context: Context) : A2DPImplBase(), Closeable { private val TAG = "PandoraA2dpSink" private val scope: CoroutineScope Loading @@ -59,7 +60,7 @@ class A2dpSink(val context: Context) : A2DPImplBase() { flow = intentFlow(context, intentFilter).shareIn(scope, SharingStarted.Eagerly) } fun deinit() { override fun close() { bluetoothAdapter.closeProfileProxy(BluetoothProfile.A2DP_SINK, bluetoothA2dpSink) scope.cancel() } Loading
android/pandora/server/src/com/android/pandora/AndroidInternal.kt +61 −33 Original line number Diff line number Diff line Loading @@ -16,34 +16,33 @@ package com.android.pandora import android.util.Log import android.bluetooth.BluetoothDevice import android.bluetooth.BluetoothManager import android.content.ComponentName import android.content.ContentUris import android.content.Context import com.google.protobuf.Empty import io.grpc.stub.StreamObserver import android.content.Intent import android.graphics.Bitmap import android.os.Environment import android.provider.MediaStore.Images.Media import android.provider.MediaStore.MediaColumns import android.provider.Telephony.* import android.telephony.SmsManager import android.telephony.SubscriptionManager import android.telephony.TelephonyManager import android.content.Intent import android.content.ComponentName import android.content.ContentUris import java.io.File import java.io.FileOutputStream import android.provider.MediaStore.Images.Media import android.provider.MediaStore.MediaColumns import android.net.Uri import kotlinx.coroutines.async import android.bluetooth.BluetoothAdapter import android.bluetooth.BluetoothDevice import android.bluetooth.BluetoothManager import android.util.Log import androidx.test.InstrumentationRegistry import androidx.test.uiautomator.By import androidx.test.uiautomator.UiDevice import androidx.test.uiautomator.Until import com.google.protobuf.Empty import io.grpc.stub.StreamObserver import java.io.Closeable import java.io.File import java.io.FileOutputStream import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.async import kotlinx.coroutines.cancel import pandora.AndroidGrpc.AndroidImplBase import pandora.AndroidProto.* Loading @@ -51,7 +50,7 @@ import pandora.AndroidProto.* private const val TAG = "PandoraAndroidInternal" @kotlinx.coroutines.ExperimentalCoroutinesApi class AndroidInternal(val context: Context) : AndroidImplBase() { class AndroidInternal(val context: Context) : AndroidImplBase(), Closeable { private val scope: CoroutineScope = CoroutineScope(Dispatchers.Default) private val INCOMING_FILE_ACCEPT_BTN = "ACCEPT" Loading @@ -73,10 +72,14 @@ class AndroidInternal(val context: Context) : AndroidImplBase() { createImageFile() } fun deinit() { override fun close() { scope.cancel() val file = File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), IMAGE_FILE_NAME) val file = File( Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), IMAGE_FILE_NAME ) if (file.exists()) { file.delete() Loading @@ -90,13 +93,19 @@ class AndroidInternal(val context: Context) : AndroidImplBase() { } } override fun setAccessPermission(request: SetAccessPermissionRequest, responseObserver: StreamObserver<Empty>) { override fun setAccessPermission( request: SetAccessPermissionRequest, responseObserver: StreamObserver<Empty> ) { grpcUnary<Empty>(scope, responseObserver) { val bluetoothDevice = request.address.toBluetoothDevice(bluetoothAdapter) when (request.accessType!!) { AccessType.ACCESS_MESSAGE -> bluetoothDevice.setMessageAccessPermission(BluetoothDevice.ACCESS_ALLOWED) AccessType.ACCESS_PHONEBOOK -> bluetoothDevice.setPhonebookAccessPermission(BluetoothDevice.ACCESS_ALLOWED) AccessType.ACCESS_SIM -> bluetoothDevice.setSimAccessPermission(BluetoothDevice.ACCESS_ALLOWED) AccessType.ACCESS_MESSAGE -> bluetoothDevice.setMessageAccessPermission(BluetoothDevice.ACCESS_ALLOWED) AccessType.ACCESS_PHONEBOOK -> bluetoothDevice.setPhonebookAccessPermission(BluetoothDevice.ACCESS_ALLOWED) AccessType.ACCESS_SIM -> bluetoothDevice.setSimAccessPermission(BluetoothDevice.ACCESS_ALLOWED) else -> {} } Empty.getDefaultInstance() Loading @@ -110,15 +119,25 @@ class AndroidInternal(val context: Context) : AndroidImplBase() { telephonyManager = telephonyManager.createForSubscriptionId(defaultSmsSub) val avdPhoneNumber = telephonyManager.getLine1Number() smsManager.sendTextMessage(avdPhoneNumber, avdPhoneNumber, generateAlphanumericString(DEFAULT_MESSAGE_LEN), null, null) smsManager.sendTextMessage( avdPhoneNumber, avdPhoneNumber, generateAlphanumericString(DEFAULT_MESSAGE_LEN), null, null ) Empty.getDefaultInstance() } } override fun acceptIncomingFile(request: Empty, responseObserver: StreamObserver<Empty>) { grpcUnary<Empty>(scope, responseObserver) { device.wait(Until.findObject(By.text(INCOMING_FILE_TITLE)), INCOMING_FILE_WAIT_TIMEOUT).click() device.wait(Until.findObject(By.text(INCOMING_FILE_ACCEPT_BTN)), INCOMING_FILE_WAIT_TIMEOUT).click() device .wait(Until.findObject(By.text(INCOMING_FILE_TITLE)), INCOMING_FILE_WAIT_TIMEOUT) .click() device .wait(Until.findObject(By.text(INCOMING_FILE_ACCEPT_BTN)), INCOMING_FILE_WAIT_TIMEOUT) .click() Empty.getDefaultInstance() } } Loading @@ -132,8 +151,11 @@ class AndroidInternal(val context: Context) : AndroidImplBase() { } suspend private fun waitAndSelectBluetoothDevice() { var selectJob = scope.async { device.wait(Until.findObject(By.textContains("Cuttlefish")), BT_DEVICE_SELECT_WAIT_TIMEOUT).click() var selectJob = scope.async { device .wait(Until.findObject(By.textContains("Cuttlefish")), BT_DEVICE_SELECT_WAIT_TIMEOUT) .click() } selectJob.await() } Loading @@ -148,14 +170,16 @@ class AndroidInternal(val context: Context) : AndroidImplBase() { sendingIntent.setComponent(ComponentName(BT_PKG_NAME, BT_OPP_LAUNCHER_ACTIVITY)) sendingIntent.putExtra(Intent.EXTRA_STREAM, contentUri) context.startActivity(sendingIntent) } catch(e: Exception) { } } catch (e: Exception) {} } private fun getImageId(fileName: String): Long { val selection = MediaColumns.DISPLAY_NAME + "=?" val selectionArgs = arrayOf(fileName) val cursor = context.getContentResolver().query(Media.EXTERNAL_CONTENT_URI, null, selection, selectionArgs, null) val cursor = context .getContentResolver() .query(Media.EXTERNAL_CONTENT_URI, null, selection, selectionArgs, null) cursor?.use { it.let { Loading @@ -168,7 +192,11 @@ class AndroidInternal(val context: Context) : AndroidImplBase() { private fun createImageFile() { val bitmapImage = Bitmap.createBitmap(30, 20, Bitmap.Config.ARGB_8888) val file = File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), IMAGE_FILE_NAME) val file = File( Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), IMAGE_FILE_NAME ) var fileOutputStream: FileOutputStream? = null if (file.exists()) { Loading
android/pandora/server/src/com/android/pandora/Avrcp.kt +3 −2 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package com.android.pandora import android.bluetooth.BluetoothManager import android.content.Context import java.io.Closeable import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.cancel Loading @@ -25,7 +26,7 @@ import pandora.AVRCPGrpc.AVRCPImplBase import pandora.AvrcpProto.* @kotlinx.coroutines.ExperimentalCoroutinesApi class Avrcp(val context: Context) : AVRCPImplBase() { class Avrcp(val context: Context) : AVRCPImplBase(), Closeable { private val TAG = "PandoraAvrcp" private val scope: CoroutineScope Loading @@ -39,7 +40,7 @@ class Avrcp(val context: Context) : AVRCPImplBase() { scope = CoroutineScope(Dispatchers.Default) } fun deinit() { override fun close() { // Deinit the CoroutineScope scope.cancel() } Loading
android/pandora/server/src/com/android/pandora/Gatt.kt +3 −2 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ 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 import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers Loading @@ -45,7 +46,7 @@ import pandora.GATTGrpc.GATTImplBase import pandora.GattProto.* @kotlinx.coroutines.ExperimentalCoroutinesApi class Gatt(private val context: Context) : GATTImplBase() { class Gatt(private val context: Context) : GATTImplBase(), Closeable { private val TAG = "PandoraGatt" private val mScope: CoroutineScope = CoroutineScope(Dispatchers.Default) Loading @@ -63,7 +64,7 @@ class Gatt(private val context: Context) : GATTImplBase() { flow = intentFlow(context, intentFilter).shareIn(mScope, SharingStarted.Eagerly) } fun deinit() { override fun close() { serverManager.server.close() mScope.cancel() } Loading