1 /* 2 * Copyright (C) 2022 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.pandora 18 19 import android.util.Log 20 import android.content.Context 21 import com.google.protobuf.Empty 22 import io.grpc.stub.StreamObserver 23 import android.provider.Telephony.* 24 import android.telephony.SmsManager 25 import android.telephony.SubscriptionManager 26 import android.telephony.TelephonyManager 27 import android.net.Uri 28 import android.bluetooth.BluetoothAdapter 29 import android.bluetooth.BluetoothDevice 30 import android.bluetooth.BluetoothManager 31 import androidx.test.InstrumentationRegistry 32 import androidx.test.uiautomator.By 33 import androidx.test.uiautomator.UiDevice 34 import androidx.test.uiautomator.Until 35 import kotlinx.coroutines.CoroutineScope 36 import kotlinx.coroutines.Dispatchers 37 import kotlinx.coroutines.cancel 38 import pandora.AndroidGrpc.AndroidImplBase 39 import pandora.AndroidProto.* 40 41 private const val TAG = "PandoraAndroidInternal" 42 43 @kotlinx.coroutines.ExperimentalCoroutinesApi 44 class AndroidInternal(val context: Context) : AndroidImplBase() { 45 46 private val scope: CoroutineScope = CoroutineScope(Dispatchers.Default) 47 private val INCOMING_FILE_ACCEPT_BTN = "ACCEPT" 48 private val INCOMING_FILE_TITLE = "Incoming file" 49 private val INCOMING_FILE_WAIT_TIMEOUT = 2000L 50 51 private val bluetoothManager = context.getSystemService(BluetoothManager::class.java)!! 52 private val bluetoothAdapter = bluetoothManager.adapter 53 private var telephonyManager = context.getSystemService(TelephonyManager::class.java) 54 private val DEFAULT_MESSAGE_LEN = 130 55 private var device: UiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) 56 deinitnull57 fun deinit() { 58 scope.cancel() 59 } 60 lognull61 override fun log(request: LogRequest, responseObserver: StreamObserver<LogResponse>) { 62 grpcUnary(scope, responseObserver) { 63 Log.i(TAG, request.text) 64 LogResponse.getDefaultInstance() 65 } 66 } 67 setAccessPermissionnull68 override fun setAccessPermission(request: SetAccessPermissionRequest, responseObserver: StreamObserver<Empty>) { 69 grpcUnary<Empty>(scope, responseObserver) { 70 val bluetoothDevice = request.address.toBluetoothDevice(bluetoothAdapter) 71 when (request.accessType!!) { 72 AccessType.ACCESS_MESSAGE -> bluetoothDevice.setMessageAccessPermission(BluetoothDevice.ACCESS_ALLOWED) 73 AccessType.ACCESS_PHONEBOOK -> bluetoothDevice.setPhonebookAccessPermission(BluetoothDevice.ACCESS_ALLOWED) 74 AccessType.ACCESS_SIM -> bluetoothDevice.setSimAccessPermission(BluetoothDevice.ACCESS_ALLOWED) 75 else -> {} 76 } 77 Empty.getDefaultInstance() 78 } 79 } 80 sendSMSnull81 override fun sendSMS(request: Empty, responseObserver: StreamObserver<Empty>) { 82 grpcUnary<Empty>(scope, responseObserver) { 83 val smsManager = SmsManager.getDefault() 84 val defaultSmsSub = SubscriptionManager.getDefaultSmsSubscriptionId() 85 telephonyManager = telephonyManager.createForSubscriptionId(defaultSmsSub) 86 val avdPhoneNumber = telephonyManager.getLine1Number() 87 88 smsManager.sendTextMessage(avdPhoneNumber, avdPhoneNumber, generateAlphanumericString(DEFAULT_MESSAGE_LEN), null, null) 89 Empty.getDefaultInstance() 90 } 91 } 92 acceptIncomingFilenull93 override fun acceptIncomingFile(request: Empty, responseObserver: StreamObserver<Empty>) { 94 grpcUnary<Empty>(scope, responseObserver) { 95 device.wait(Until.findObject(By.text(INCOMING_FILE_TITLE)), INCOMING_FILE_WAIT_TIMEOUT).click() 96 device.wait(Until.findObject(By.text(INCOMING_FILE_ACCEPT_BTN)), INCOMING_FILE_WAIT_TIMEOUT).click() 97 Empty.getDefaultInstance() 98 } 99 } 100 } 101