• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.PendingIntent;
20 import android.app.Service;
21 import android.bluetooth.BluetoothAdapter;
22 import android.bluetooth.BluetoothDevice;
23 import android.bluetooth.BluetoothMapClient;
24 import android.bluetooth.BluetoothProfile;
25 import android.bluetooth.BluetoothUuid;
26 import android.content.BroadcastReceiver;
27 import android.content.Context;
28 import android.content.Intent;
29 import android.content.IntentFilter;
30 import android.net.Uri;
31 import android.os.ParcelUuid;
32 
33 import com.googlecode.android_scripting.Log;
34 import com.googlecode.android_scripting.facade.EventFacade;
35 import com.googlecode.android_scripting.facade.FacadeManager;
36 import com.googlecode.android_scripting.jsonrpc.RpcReceiver;
37 import com.googlecode.android_scripting.rpc.Rpc;
38 import com.googlecode.android_scripting.rpc.RpcParameter;
39 
40 import java.util.List;
41 
42 public class BluetoothMapClientFacade extends RpcReceiver {
43     static final ParcelUuid[] MAP_UUIDS = {
44             BluetoothUuid.MAP,
45             BluetoothUuid.MNS,
46             BluetoothUuid.MAS,
47     };
48     public static final String MAP_EVENT = "MapMessageReceived";
49     public static final String MAP_SMS_SENT_SUCCESS = "SmsSentSuccess";
50     public static final String MAP_SMS_DELIVER_SUCCESS = "SmsDeliverSuccess";
51 
52     private final Service mService;
53     private final BluetoothAdapter mBluetoothAdapter;
54     private final EventFacade mEventFacade;
55     private final NotificationReceiver mNotificationReceiver;
56 
57     private Intent mSendIntent;
58     private Intent mDeliveryIntent;
59     private PendingIntent mSentIntent;
60     private PendingIntent mDeliveredIntent;
61 
62     private static boolean sIsMapReady = false;
63     private static BluetoothMapClient sMapProfile = null;
64 
BluetoothMapClientFacade(FacadeManager manager)65     public BluetoothMapClientFacade(FacadeManager manager) {
66         super(manager);
67         Log.d("Creating BluetoothMapClientFacade");
68         mService = manager.getService();
69         mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
70         mBluetoothAdapter.getProfileProxy(mService, new MapServiceListener(),
71                 BluetoothProfile.MAP_CLIENT);
72         mEventFacade = manager.getReceiver(EventFacade.class);
73 
74         mNotificationReceiver = new NotificationReceiver();
75         mSendIntent = new Intent(
76                 BluetoothMapClient.ACTION_MESSAGE_SENT_SUCCESSFULLY);
77         mDeliveryIntent = new Intent(
78                 BluetoothMapClient.ACTION_MESSAGE_DELIVERED_SUCCESSFULLY);
79         IntentFilter intentFilter = new IntentFilter();
80         intentFilter.addAction(BluetoothMapClient.ACTION_MESSAGE_RECEIVED);
81         intentFilter.addAction(
82                 BluetoothMapClient.ACTION_MESSAGE_SENT_SUCCESSFULLY);
83         intentFilter.addAction(
84                 BluetoothMapClient.ACTION_MESSAGE_DELIVERED_SUCCESSFULLY);
85         mService.registerReceiver(mNotificationReceiver, intentFilter);
86         Log.d("notification receiver registered");
87     }
88 
89     class MapServiceListener implements BluetoothProfile.ServiceListener {
90         @Override
onServiceConnected(int profile, BluetoothProfile proxy)91         public void onServiceConnected(int profile, BluetoothProfile proxy) {
92             sMapProfile = (BluetoothMapClient) proxy;
93             sIsMapReady = true;
94         }
95 
96         @Override
onServiceDisconnected(int profile)97         public void onServiceDisconnected(int profile) {
98             sIsMapReady = false;
99         }
100     }
101 
mapClientConnect(BluetoothDevice device)102     public Boolean mapClientConnect(BluetoothDevice device) {
103         if (sMapProfile == null) return false;
104         return sMapProfile.connect(device);
105     }
106 
mapClientDisconnect(BluetoothDevice device)107     public Boolean mapClientDisconnect(BluetoothDevice device) {
108         if (sMapProfile == null) return false;
109         return sMapProfile.disconnect(device);
110     }
111 
112     @Rpc(description = "Connect to an MAP MSE device.")
bluetoothMapClientConnect( @pcParametername = "device", description = "Name or MAC address of a bluetooth " + "device.") String device)113     public Boolean bluetoothMapClientConnect(
114             @RpcParameter(name = "device",
115                     description = "Name or MAC address of a bluetooth "
116                     + "device.")
117                     String device)
118             throws Exception {
119         if (sMapProfile == null) return false;
120         BluetoothDevice mDevice = BluetoothFacade.getDevice(
121                 mBluetoothAdapter.getBondedDevices(), device);
122         Log.d("Connecting to device " + mDevice.getAlias());
123         return sMapProfile.connect(mDevice);
124     }
125 
126     @Rpc(description = "Send a (text) message via bluetooth.")
mapSendMessage( @pcParametername = "deviceID", description = "Name or MAC address of a device.") String deviceID, @RpcParameter(name = "phoneNumbers", description = "Phone number of contact.") String[] phoneNumbers, @RpcParameter(name = "message", description = "Message to send.") String message)127     public Boolean mapSendMessage(
128             @RpcParameter(name = "deviceID",
129                     description = "Name or MAC address of a device.")
130                     String deviceID,
131             @RpcParameter(name = "phoneNumbers",
132                     description = "Phone number of contact.")
133                     String[] phoneNumbers,
134             @RpcParameter(name = "message",
135                     description = "Message to send.") String message) {
136         try {
137             BluetoothDevice device =
138                     BluetoothFacade.getDevice(
139                             sMapProfile.getConnectedDevices(), deviceID);
140             mSentIntent = PendingIntent.getBroadcast(mService, 0, mSendIntent,
141                     PendingIntent.FLAG_ONE_SHOT);
142             mDeliveredIntent = PendingIntent.getBroadcast(
143                     mService, 0, mDeliveryIntent,
144                     PendingIntent.FLAG_ONE_SHOT);
145             Uri[] contacts = new Uri[phoneNumbers.length];
146             for (int i = 0; i < phoneNumbers.length; i++) {
147                 Log.d("PhoneNumber count: " + phoneNumbers.length + " = "
148                         + phoneNumbers[i]);
149                 contacts[i] = Uri.parse(phoneNumbers[i]);
150             }
151             return sMapProfile.sendMessage(device, contacts, message, mSentIntent,
152                     mDeliveredIntent);
153         } catch (Exception e) {
154             Log.d("Error sending message, no such device " + e.toString());
155         }
156         return false;
157     }
158 
mapDisconnect(BluetoothDevice device)159     public Boolean mapDisconnect(BluetoothDevice device) {
160         if (sMapProfile.getPriority(device) > BluetoothProfile.PRIORITY_ON) {
161             sMapProfile.setPriority(device, BluetoothProfile.PRIORITY_ON);
162         }
163         return sMapProfile.disconnect(device);
164     }
165 
166     @Rpc(description = "Is Map profile ready.")
bluetoothMapClientIsReady()167     public Boolean bluetoothMapClientIsReady() {
168         return sIsMapReady;
169     }
170 
171     @Rpc(description = "Disconnect an MAP device.")
bluetoothMapClientDisconnect( @pcParametername = "deviceID", description = "Name or MAC address of a device.") String deviceID)172     public Boolean bluetoothMapClientDisconnect(
173             @RpcParameter(name = "deviceID",
174                     description = "Name or MAC address of a device.")
175                     String deviceID)
176             throws Exception {
177         if (sMapProfile == null) return false;
178         List<BluetoothDevice> connectedMapDevices =
179                 sMapProfile.getConnectedDevices();
180         Log.d("Connected map devices: " + connectedMapDevices);
181         BluetoothDevice mDevice = BluetoothFacade.getDevice(
182                 connectedMapDevices, deviceID);
183         if (!connectedMapDevices.isEmpty()
184                 && connectedMapDevices.get(0).equals(mDevice)) {
185             if (sMapProfile.getPriority(mDevice) > BluetoothProfile.PRIORITY_ON) {
186                 sMapProfile.setPriority(mDevice, BluetoothProfile.PRIORITY_ON);
187             }
188             return sMapProfile.disconnect(mDevice);
189         } else {
190             return false;
191         }
192     }
193 
194     @Rpc(description = "Get all the devices connected through MAP.")
bluetoothMapClientGetConnectedDevices()195     public List<BluetoothDevice> bluetoothMapClientGetConnectedDevices() {
196         while (!sIsMapReady) ;
197         return sMapProfile.getDevicesMatchingConnectionStates(
198                 new int[]{BluetoothProfile.STATE_CONNECTED,
199                         BluetoothProfile.STATE_CONNECTING,
200                         BluetoothProfile.STATE_DISCONNECTING});
201     }
202 
203     @Override
shutdown()204     public void shutdown() {
205         mService.unregisterReceiver(mNotificationReceiver);
206     }
207 
208     public class NotificationReceiver extends BroadcastReceiver {
209         @Override
onReceive(Context context, Intent intent)210         public void onReceive(Context context, Intent intent) {
211             Log.d("OnReceive" + intent);
212             String action = intent.getAction();
213             if (action.equals(BluetoothMapClient.ACTION_MESSAGE_RECEIVED)) {
214                 mEventFacade.postEvent(MAP_EVENT,
215                         intent.getStringExtra(android.content.Intent.EXTRA_TEXT));
216             } else if (action.equals(
217                     BluetoothMapClient.ACTION_MESSAGE_SENT_SUCCESSFULLY)) {
218                 mEventFacade.postEvent(MAP_SMS_SENT_SUCCESS,
219                         intent.getStringExtra(
220                             android.content.Intent.EXTRA_TEXT));
221             } else if (action.equals(
222                     BluetoothMapClient.ACTION_MESSAGE_DELIVERED_SUCCESSFULLY)) {
223                 mEventFacade.postEvent(MAP_SMS_DELIVER_SUCCESS,
224                         intent.getStringExtra(android.content.Intent.EXTRA_TEXT));
225             }
226         }
227     }
228 }
229