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.bluetooth.BluetoothManager 20 import android.bluetooth.BluetoothProfile 21 import android.content.Context 22 import android.util.Log 23 import io.grpc.Server as GrpcServer 24 import io.grpc.netty.shaded.io.grpc.netty.NettyServerBuilder 25 26 @kotlinx.coroutines.ExperimentalCoroutinesApi 27 class Server(context: Context) { 28 29 private val TAG = "PandoraServer" 30 private val GRPC_PORT = 8999 31 32 private var host: Host 33 private var a2dp: A2dp? = null 34 private var a2dpSink: A2dpSink? = null 35 private var avrcp: Avrcp 36 private var gatt: Gatt 37 private var hfp: Hfp? = null 38 private var hfpHandsfree: HfpHandsfree? = null 39 private var hid: Hid 40 private var l2cap: L2cap 41 private var mediaplayer: MediaPlayer 42 private var pbap: Pbap 43 private var rfcomm: Rfcomm 44 private var security: Security 45 private var securityStorage: SecurityStorage 46 private var androidInternal: AndroidInternal 47 private var grpcServer: GrpcServer 48 49 init { 50 security = Security(context) 51 host = Host(context, security, this) 52 avrcp = Avrcp(context) 53 gatt = Gatt(context) 54 hid = Hid(context) 55 l2cap = L2cap(context) 56 mediaplayer = MediaPlayer(context) 57 pbap = Pbap(context) 58 rfcomm = Rfcomm(context) 59 securityStorage = SecurityStorage(context) 60 androidInternal = AndroidInternal(context) 61 62 val grpcServerBuilder = 63 NettyServerBuilder.forPort(GRPC_PORT) 64 .addService(host) 65 .addService(avrcp) 66 .addService(gatt) 67 .addService(hid) 68 .addService(l2cap) 69 .addService(mediaplayer) 70 .addService(pbap) 71 .addService(rfcomm) 72 .addService(security) 73 .addService(securityStorage) 74 .addService(androidInternal) 75 76 val bluetoothAdapter = context.getSystemService(BluetoothManager::class.java)!!.adapter 77 val is_a2dp_source = bluetoothAdapter.getSupportedProfiles().contains(BluetoothProfile.A2DP) 78 if (is_a2dp_source) { 79 a2dp = A2dp(context) 80 grpcServerBuilder.addService(a2dp!!) 81 } else { 82 a2dpSink = A2dpSink(context) 83 grpcServerBuilder.addService(a2dpSink!!) 84 } 85 86 val is_hfp_hf = bluetoothAdapter.getSupportedProfiles().contains(BluetoothProfile.HEADSET_CLIENT) 87 if (is_hfp_hf) { 88 hfpHandsfree = HfpHandsfree(context) 89 grpcServerBuilder.addService(hfpHandsfree!!) 90 } else { 91 hfp = Hfp(context) 92 grpcServerBuilder.addService(hfp!!) 93 } 94 95 grpcServer = grpcServerBuilder.build() 96 97 Log.d(TAG, "Starting Pandora Server") 98 grpcServer.start() 99 Log.d(TAG, "Pandora Server started at $GRPC_PORT") 100 } 101 shutdownnull102 fun shutdown() = grpcServer.shutdown() 103 104 fun awaitTermination() = grpcServer.awaitTermination() 105 106 fun deinit() { 107 host.deinit() 108 a2dp?.deinit() 109 a2dpSink?.deinit() 110 avrcp.deinit() 111 gatt.deinit() 112 hfp?.deinit() 113 hfpHandsfree?.deinit() 114 hid.deinit() 115 l2cap.deinit() 116 mediaplayer.deinit() 117 pbap.deinit() 118 rfcomm.deinit() 119 security.deinit() 120 securityStorage.deinit() 121 androidInternal.deinit() 122 } 123 } 124