1 /*
2  * Copyright (C) 2016 Google Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5  * use this file except in compliance with the License. You may obtain a copy of
6  * 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, WITHOUT
12  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13  * License for the specific language governing permissions and limitations under
14  * the License.
15  */
16 
17 package com.googlecode.android_scripting.facade.bluetooth;
18 
19 import java.util.List;
20 
21 import android.app.Service;
22 import android.bluetooth.BluetoothA2dpSink;
23 import android.bluetooth.BluetoothAdapter;
24 import android.bluetooth.BluetoothDevice;
25 import android.bluetooth.BluetoothProfile;
26 import android.bluetooth.BluetoothUuid;
27 import android.os.ParcelUuid;
28 
29 import com.googlecode.android_scripting.Log;
30 import com.googlecode.android_scripting.facade.FacadeManager;
31 import com.googlecode.android_scripting.jsonrpc.RpcReceiver;
32 import com.googlecode.android_scripting.rpc.Rpc;
33 import com.googlecode.android_scripting.rpc.RpcParameter;
34 
35 public class BluetoothA2dpSinkFacade extends RpcReceiver {
36   static final ParcelUuid[] SOURCE_UUIDS = {
37     BluetoothUuid.AudioSource,
38   };
39 
40   private final Service mService;
41   private final BluetoothAdapter mBluetoothAdapter;
42 
43   private static BluetoothA2dpSink sA2dpSinkProfile = null;
44 
BluetoothA2dpSinkFacade(FacadeManager manager)45   public BluetoothA2dpSinkFacade(FacadeManager manager) {
46     super(manager);
47     mService = manager.getService();
48     mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
49     mBluetoothAdapter.getProfileProxy(mService, new A2dpSinkServiceListener(),
50         BluetoothProfile.A2DP_SINK);
51   }
52 
53   class A2dpSinkServiceListener implements BluetoothProfile.ServiceListener {
54     @Override
onServiceConnected(int profile, BluetoothProfile proxy)55     public void onServiceConnected(int profile, BluetoothProfile proxy) {
56       sA2dpSinkProfile = (BluetoothA2dpSink) proxy;
57     }
58 
59     @Override
onServiceDisconnected(int profile)60     public void onServiceDisconnected(int profile) {
61       sA2dpSinkProfile = null;
62     }
63   }
64 
a2dpSinkConnect(BluetoothDevice device)65   public Boolean a2dpSinkConnect(BluetoothDevice device) {
66     if (sA2dpSinkProfile == null) return false;
67     return sA2dpSinkProfile.connect(device);
68   }
69 
a2dpSinkDisconnect(BluetoothDevice device)70   public Boolean a2dpSinkDisconnect(BluetoothDevice device) {
71     if (sA2dpSinkProfile == null) return false;
72     return sA2dpSinkProfile.disconnect(device);
73   }
74 
75   @Rpc(description = "Is A2dpSink profile ready.")
bluetoothA2dpSinkIsReady()76   public Boolean bluetoothA2dpSinkIsReady() {
77     return (sA2dpSinkProfile != null);
78   }
79 
80   @Rpc(description = "Connect to an A2DP Sink device.")
bluetoothA2dpSinkConnect( @pcParametername = "device", description = "Name or MAC address of a bluetooth device.") String device)81   public Boolean bluetoothA2dpSinkConnect(
82       @RpcParameter(name = "device", description = "Name or MAC address of a bluetooth device.")
83       String device)
84       throws Exception {
85     if (sA2dpSinkProfile == null) return false;
86     BluetoothDevice mDevice = BluetoothFacade.getDevice(BluetoothFacade.DiscoveredDevices, device);
87     Log.d("Connecting to device " + mDevice.getAliasName());
88     return a2dpSinkConnect(mDevice);
89   }
90 
91   @Rpc(description = "Disconnect an A2DP Sink device.")
bluetoothA2dpSinkDisconnect( @pcParametername = "device", description = "Name or MAC address of a device.") String deviceStr)92   public Boolean bluetoothA2dpSinkDisconnect(
93       @RpcParameter(name = "device", description = "Name or MAC address of a device.")
94       String deviceStr) {
95     if (sA2dpSinkProfile == null) return false;
96     Log.d("Connected devices: " + sA2dpSinkProfile.getConnectedDevices());
97     BluetoothDevice device = null;
98     try {
99       device = BluetoothFacade.getDevice(sA2dpSinkProfile.getConnectedDevices(), deviceStr);
100       return a2dpSinkDisconnect(device);
101     } catch (Exception e) {
102         // Do nothing here. Since it is disconnect this function should force shutdown anyways.
103         Log.d("bluetoothA2dpSinkDisconnect error while getDevice " + e);
104     }
105     return false;
106   }
107 
108   @Rpc(description = "Get all the devices connected through A2DP Sink.")
bluetoothA2dpSinkGetConnectedDevices()109   public List<BluetoothDevice> bluetoothA2dpSinkGetConnectedDevices() {
110     return sA2dpSinkProfile.getConnectedDevices();
111   }
112 
113   @Rpc(description = "Get the connection status of a device.")
bluetoothA2dpSinkGetConnectionStatus( @pcParametername = "deviceID", description = "Name or MAC address of a bluetooth device.") String deviceID)114   public Integer bluetoothA2dpSinkGetConnectionStatus(
115       @RpcParameter(name = "deviceID",
116                     description = "Name or MAC address of a bluetooth device.")
117         String deviceID) {
118     if (sA2dpSinkProfile == null) {
119       return BluetoothProfile.STATE_DISCONNECTED;
120     }
121     List<BluetoothDevice> deviceList = sA2dpSinkProfile.getConnectedDevices();
122     BluetoothDevice device;
123     try {
124       device = BluetoothFacade.getDevice(deviceList, deviceID);
125     } catch (Exception e) {
126       Log.e(e);
127       return BluetoothProfile.STATE_DISCONNECTED;
128     }
129     return sA2dpSinkProfile.getConnectionState(device);
130   }
131 
132   @Override
shutdown()133   public void shutdown() {
134   }
135 }
136