1 /*
2  * Copyright (C) 2017 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.googlecode.android_scripting.facade.bluetooth;
18 
19 import android.app.Service;
20 import android.bluetooth.BluetoothAdapter;
21 import android.bluetooth.BluetoothDevice;
22 import android.bluetooth.BluetoothMap;
23 import android.bluetooth.BluetoothProfile;
24 import android.bluetooth.BluetoothUuid;
25 import android.os.ParcelUuid;
26 
27 import com.googlecode.android_scripting.Log;
28 import com.googlecode.android_scripting.facade.FacadeManager;
29 import com.googlecode.android_scripting.jsonrpc.RpcReceiver;
30 import com.googlecode.android_scripting.rpc.Rpc;
31 import com.googlecode.android_scripting.rpc.RpcParameter;
32 
33 import java.util.List;
34 
35 public class BluetoothMapFacade extends RpcReceiver {
36     static final ParcelUuid[] MAP_UUIDS = {
37         BluetoothUuid.MAP,
38         BluetoothUuid.MNS,
39         BluetoothUuid.MAS,
40     };
41     private final Service mService;
42     private final BluetoothAdapter mBluetoothAdapter;
43 
44     private static boolean sIsMapReady = false;
45     private static BluetoothMap sMapProfile = null;
46 
BluetoothMapFacade(FacadeManager manager)47     public BluetoothMapFacade(FacadeManager manager) {
48         super(manager);
49         mService = manager.getService();
50         mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
51         mBluetoothAdapter.getProfileProxy(mService, new MapServiceListener(),
52         BluetoothProfile.MAP);
53     }
54 
55     class MapServiceListener implements BluetoothProfile.ServiceListener {
56         @Override
onServiceConnected(int profile, BluetoothProfile proxy)57         public void onServiceConnected(int profile, BluetoothProfile proxy) {
58             sMapProfile = (BluetoothMap) proxy;
59             sIsMapReady = true;
60         }
61 
62         @Override
onServiceDisconnected(int profile)63         public void onServiceDisconnected(int profile) {
64             sIsMapReady = false;
65         }
66     }
67 
68     /**
69      * Disconnect Map Profile.
70      * @param device - the BluetoothDevice object to connect to.
71      * @return if the disconnection was successfull or not.
72      */
mapDisconnect(BluetoothDevice device)73     public Boolean mapDisconnect(BluetoothDevice device) {
74         if (sMapProfile.getConnectionPolicy(device) > BluetoothProfile.CONNECTION_POLICY_ALLOWED) {
75             sMapProfile.setConnectionPolicy(device, BluetoothProfile.CONNECTION_POLICY_ALLOWED);
76         }
77         return sMapProfile.disconnect(device);
78     }
79 
80     /**
81      * Is Map profile ready.
82      * @return if Map profile is ready or not.
83      */
84     @Rpc(description = "Is Map profile ready.")
bluetoothMapIsReady()85     public Boolean bluetoothMapIsReady() {
86     return sIsMapReady;
87     }
88 
89     /**
90      * Disconnect an MAP device.
91      * @param deviceID - Name or MAC address of a bluetooth device.
92      * @return True if the disconnection was successful; otherwise False.
93      */
94     @Rpc(description = "Disconnect an MAP device.")
bluetoothMapDisconnect( @pcParametername = "deviceID", description = "Name or MAC address of a device.") String deviceID)95     public Boolean bluetoothMapDisconnect(
96             @RpcParameter(name = "deviceID",
97                 description = "Name or MAC address of a device.")
98                     String deviceID) throws Exception {
99         if (sMapProfile == null) return false;
100         List<BluetoothDevice> connectedMapDevices =
101                 sMapProfile.getConnectedDevices();
102         Log.d("Connected map devices: " + connectedMapDevices);
103         BluetoothDevice mDevice = BluetoothFacade.getDevice(connectedMapDevices, deviceID);
104         if (!connectedMapDevices.isEmpty()
105                 && connectedMapDevices.get(0).equals(mDevice)) {
106             if (sMapProfile.getConnectionPolicy(mDevice)
107                     > BluetoothProfile.CONNECTION_POLICY_ALLOWED) {
108                 sMapProfile.setConnectionPolicy(
109                         mDevice, BluetoothProfile.CONNECTION_POLICY_ALLOWED);
110             }
111             return sMapProfile.disconnect(mDevice);
112         } else {
113             return false;
114         }
115     }
116 
117     /**
118      * Get all the devices connected through MAP.
119      * @return List of all the devices connected through MAP.
120      */
121     @Rpc(description = "Get all the devices connected through MAP.")
bluetoothMapGetConnectedDevices()122     public List<BluetoothDevice> bluetoothMapGetConnectedDevices() {
123         if (!sIsMapReady) return null;
124         return sMapProfile.getDevicesMatchingConnectionStates(
125                 new int[] {BluetoothProfile.STATE_CONNECTED,
126                     BluetoothProfile.STATE_CONNECTING,
127                     BluetoothProfile.STATE_DISCONNECTING});
128     }
129 
130     /**
131      * Get the currently connected remote Bluetooth device (PCE).
132      * @return remote Bluetooth device which is currently conencted.
133      */
134     @Rpc(description =
135             "Get the currently connected remote Bluetooth device (PCE).")
bluetoothMapGetClient()136     public BluetoothDevice bluetoothMapGetClient() {
137         if (sMapProfile == null) return null;
138         return sMapProfile.getClient();
139     }
140 
141     @Override
shutdown()142     public void shutdown() {
143     }
144 }
145