• 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(BluetoothMapClient.ACTION_MESSAGE_SENT_SUCCESSFULLY);
76         mDeliveryIntent = new Intent(BluetoothMapClient.ACTION_MESSAGE_DELIVERED_SUCCESSFULLY);
77         IntentFilter intentFilter = new IntentFilter();
78         intentFilter.addAction(BluetoothMapClient.ACTION_MESSAGE_RECEIVED);
79         intentFilter.addAction(BluetoothMapClient.ACTION_MESSAGE_SENT_SUCCESSFULLY);
80         intentFilter.addAction(BluetoothMapClient.ACTION_MESSAGE_DELIVERED_SUCCESSFULLY);
81         mService.registerReceiver(mNotificationReceiver, intentFilter);
82         Log.d("notification receiver registered");
83     }
84 
85     class MapServiceListener implements BluetoothProfile.ServiceListener {
86         @Override
onServiceConnected(int profile, BluetoothProfile proxy)87         public void onServiceConnected(int profile, BluetoothProfile proxy) {
88             sMapProfile = (BluetoothMapClient) proxy;
89             sIsMapReady = true;
90         }
91 
92         @Override
onServiceDisconnected(int profile)93         public void onServiceDisconnected(int profile) {
94             sIsMapReady = false;
95         }
96     }
97 
mapClientConnect(BluetoothDevice device)98     public Boolean mapClientConnect(BluetoothDevice device) {
99         if (sMapProfile == null) return false;
100         return sMapProfile.connect(device);
101     }
102 
mapClientDisconnect(BluetoothDevice device)103     public Boolean mapClientDisconnect(BluetoothDevice device) {
104         if (sMapProfile == null) return false;
105         return sMapProfile.disconnect(device);
106     }
107 
108     @Rpc(description = "Connect to an MAP MSE device.")
bluetoothMapClientConnect( @pcParametername = "device", description = "Name or MAC address of a bluetooth " + "device.") String device)109     public Boolean bluetoothMapClientConnect(
110             @RpcParameter(name = "device", description = "Name or MAC address of a bluetooth "
111                     + "device.")
112                     String device)
113             throws Exception {
114         if (sMapProfile == null) return false;
115         BluetoothDevice mDevice = BluetoothFacade.getDevice(mBluetoothAdapter.getBondedDevices(),
116                 device);
117         Log.d("Connecting to device " + mDevice.getAliasName());
118         return sMapProfile.connect(mDevice);
119     }
120 
121     @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)122     public Boolean mapSendMessage(
123             @RpcParameter(name = "deviceID", description = "Name or MAC address of a device.")
124                     String deviceID,
125             @RpcParameter(name = "phoneNumbers", description = "Phone number of contact.")
126                     String[] phoneNumbers,
127             @RpcParameter(name = "message", description = "Message to send.") String message) {
128         try {
129             BluetoothDevice device =
130                     BluetoothFacade.getDevice(sMapProfile.getConnectedDevices(), deviceID);
131             mSentIntent = PendingIntent.getBroadcast(mService, 0, mSendIntent,
132                     PendingIntent.FLAG_ONE_SHOT);
133             mDeliveredIntent = PendingIntent.getBroadcast(mService, 0, mDeliveryIntent,
134                     PendingIntent.FLAG_ONE_SHOT);
135             Uri[] contacts = new Uri[phoneNumbers.length];
136             for (int i = 0; i < phoneNumbers.length; i++) {
137                 Log.d("PhoneNumber count: " + phoneNumbers.length + " = " + phoneNumbers[i]);
138                 contacts[i] = Uri.parse(phoneNumbers[i]);
139             }
140             return sMapProfile.sendMessage(device, contacts, message, mSentIntent,
141                     mDeliveredIntent);
142         } catch (Exception e) {
143             Log.d("Error sending message, no such device " + e.toString());
144         }
145         return false;
146     }
147 
mapDisconnect(BluetoothDevice device)148     public Boolean mapDisconnect(BluetoothDevice device) {
149         if (sMapProfile.getPriority(device) > BluetoothProfile.PRIORITY_ON) {
150             sMapProfile.setPriority(device, BluetoothProfile.PRIORITY_ON);
151         }
152         return sMapProfile.disconnect(device);
153     }
154 
155     @Rpc(description = "Is Map profile ready.")
bluetoothMapClientIsReady()156     public Boolean bluetoothMapClientIsReady() {
157         return sIsMapReady;
158     }
159 
160     @Rpc(description = "Disconnect an MAP device.")
bluetoothMapClientDisconnect( @pcParametername = "deviceID", description = "Name or MAC address of a device.") String deviceID)161     public Boolean bluetoothMapClientDisconnect(
162             @RpcParameter(name = "deviceID", description = "Name or MAC address of a device.")
163                     String deviceID)
164             throws Exception {
165         if (sMapProfile == null) return false;
166         List<BluetoothDevice> connectedMapDevices = sMapProfile.getConnectedDevices();
167         Log.d("Connected map devices: " + connectedMapDevices);
168         BluetoothDevice mDevice = BluetoothFacade.getDevice(connectedMapDevices, deviceID);
169         if (!connectedMapDevices.isEmpty() && connectedMapDevices.get(0).equals(mDevice)) {
170             if (sMapProfile.getPriority(mDevice) > BluetoothProfile.PRIORITY_ON) {
171                 sMapProfile.setPriority(mDevice, BluetoothProfile.PRIORITY_ON);
172             }
173             return sMapProfile.disconnect(mDevice);
174         } else {
175             return false;
176         }
177     }
178 
179     @Rpc(description = "Get all the devices connected through MAP.")
bluetoothMapClientGetConnectedDevices()180     public List<BluetoothDevice> bluetoothMapClientGetConnectedDevices() {
181         while (!sIsMapReady) ;
182         return sMapProfile.getDevicesMatchingConnectionStates(
183                 new int[]{BluetoothProfile.STATE_CONNECTED,
184                         BluetoothProfile.STATE_CONNECTING,
185                         BluetoothProfile.STATE_DISCONNECTING});
186     }
187 
188     @Override
shutdown()189     public void shutdown() {
190         mService.unregisterReceiver(mNotificationReceiver);
191     }
192 
193     public class NotificationReceiver extends BroadcastReceiver {
194         @Override
onReceive(Context context, Intent intent)195         public void onReceive(Context context, Intent intent) {
196             Log.d("OnReceive" + intent);
197             String action = intent.getAction();
198             if (action.equals(BluetoothMapClient.ACTION_MESSAGE_RECEIVED)) {
199                 mEventFacade.postEvent(MAP_EVENT,
200                         intent.getStringExtra(android.content.Intent.EXTRA_TEXT));
201             } else if (action.equals(BluetoothMapClient.ACTION_MESSAGE_SENT_SUCCESSFULLY)) {
202                 mEventFacade.postEvent(MAP_SMS_SENT_SUCCESS,
203                         intent.getStringExtra(android.content.Intent.EXTRA_TEXT));
204             } else if (action.equals(BluetoothMapClient.ACTION_MESSAGE_DELIVERED_SUCCESSFULLY)) {
205                 mEventFacade.postEvent(MAP_SMS_DELIVER_SUCCESS,
206                         intent.getStringExtra(android.content.Intent.EXTRA_TEXT));
207             }
208         }
209     }
210 }
211