• 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.bluetooth.BluetoothDevice;
20 import android.content.BroadcastReceiver;
21 import android.content.Context;
22 import android.content.Intent;
23 import android.os.Bundle;
24 
25 import com.googlecode.android_scripting.Log;
26 import com.googlecode.android_scripting.event.Event;
27 import com.googlecode.android_scripting.facade.EventFacade;
28 
29 public class BluetoothPairingHelper extends BroadcastReceiver {
30     private final EventFacade mEventFacade;
31     private static final int DEFAULT_TIMEOUT_MS = 5000;
32     private boolean mAutoConfirm = true;
33 
BluetoothPairingHelper(EventFacade eventFacade)34     public BluetoothPairingHelper(EventFacade eventFacade) {
35         super();
36         mEventFacade = eventFacade;
37         Log.d("Pairing helper created.");
38     }
39 
40   /**
41    *  Confirms bluetooth connection/bonding requests.
42    */
43     @Override
onReceive(Context c, Intent intent)44     public void onReceive(Context c, Intent intent) {
45         String action = intent.getAction();
46         Bundle result = new Bundle();
47         Log.d("Bluetooth pairing intent received: " + action);
48         BluetoothDevice mDevice = intent.getParcelableExtra(
49                 BluetoothDevice.EXTRA_DEVICE);
50         if (action.equals(BluetoothDevice.ACTION_PAIRING_REQUEST)) {
51             mDevice.setMessageAccessPermission(BluetoothDevice.ACCESS_ALLOWED);
52             mDevice.setPhonebookAccessPermission(
53                     BluetoothDevice.ACCESS_ALLOWED);
54             int type = intent.getIntExtra(
55                     BluetoothDevice.EXTRA_PAIRING_VARIANT,
56                         BluetoothDevice.ERROR);
57             Log.d("Processing Action Paring Request with type " + type);
58             int pin = intent.getIntExtra(BluetoothDevice.EXTRA_PAIRING_KEY, 0);
59             String deviceAddress = mDevice.getAddress();
60             result.putInt("Pin", pin);
61             result.putInt("PairingVariant", type);
62             result.putString("DeviceAddress", deviceAddress);
63             mEventFacade.postEvent("BluetoothActionPairingRequest",
64                     result.clone());
65             result.clear();
66             if (type == BluetoothDevice.PAIRING_VARIANT_CONSENT) {
67                 mDevice.setPairingConfirmation(true);
68                 Log.d("Connection auto-confirmed by consent");
69                 // Abort the broadcast so Settings app doesn't get it.
70                 abortBroadcast();
71             } else if (type
72                     == BluetoothDevice.PAIRING_VARIANT_PASSKEY_CONFIRMATION) {
73                 if (mAutoConfirm) {
74                     mDevice.setPairingConfirmation(true);
75                     Log.d("Connection auto-confirmed");
76                 } else {
77                     // Wait for confirmation
78                     Event userConfirmEvent = null;
79                     try {
80                         userConfirmEvent = mEventFacade.eventWaitFor(
81                                 "BluetoothActionPairingRequestUserConfirm",
82                                      true, DEFAULT_TIMEOUT_MS);
83                     } catch (InterruptedException e) {
84                         Log.d("Connection interrupted");
85                         userConfirmEvent = null;
86                     }
87                     if (userConfirmEvent == null) {
88                         Log.d("Null response received from test server or timeout");
89                         mDevice.setPairingConfirmation(false);
90                     } else {
91                         String userConfirmEventData =
92                                 (String) userConfirmEvent.getData();
93                         if (userConfirmEventData.equalsIgnoreCase("True")) {
94                             mDevice.setPairingConfirmation(true);
95                             Log.d("Connection confirmed");
96                         } else {
97                             mDevice.setPairingConfirmation(false);
98                             Log.d("Connection rejected");
99                         }
100                     }
101                 }
102                 // Abort the broadcast so Settings app doesn't get it.
103                 abortBroadcast();
104             }
105         } else if (action.equals(
106                 BluetoothDevice.ACTION_CONNECTION_ACCESS_REQUEST)) {
107             int type = intent.getIntExtra(
108                     BluetoothDevice.EXTRA_ACCESS_REQUEST_TYPE,
109                         BluetoothDevice.ERROR);
110             Log.d("Processing Action Connection Access Request type " + type);
111             if (type == BluetoothDevice.REQUEST_TYPE_MESSAGE_ACCESS
112                     || type == BluetoothDevice.REQUEST_TYPE_PHONEBOOK_ACCESS
113                         || type
114                             == BluetoothDevice.REQUEST_TYPE_PROFILE_CONNECTION) {
115                 Intent newIntent =
116                         new Intent(
117                             BluetoothDevice.ACTION_CONNECTION_ACCESS_REPLY);
118                 String mReturnPackage =
119                         intent.getStringExtra(
120                         BluetoothDevice.EXTRA_PACKAGE_NAME);
121                 String mReturnClass =
122                         intent.getStringExtra(BluetoothDevice.EXTRA_CLASS_NAME);
123                 int mRequestType =
124                         intent.getIntExtra(
125                             BluetoothDevice.EXTRA_ACCESS_REQUEST_TYPE,
126                                 BluetoothDevice.REQUEST_TYPE_MESSAGE_ACCESS);
127                 if (mReturnPackage != null && mReturnClass != null) {
128                     newIntent.setClassName(mReturnPackage, mReturnClass);
129                 }
130                 newIntent.putExtra(BluetoothDevice.EXTRA_CONNECTION_ACCESS_RESULT,
131                         BluetoothDevice.CONNECTION_ACCESS_YES);
132                 newIntent.putExtra(BluetoothDevice.EXTRA_ALWAYS_ALLOWED, true);
133                 newIntent.putExtra(BluetoothDevice.EXTRA_DEVICE, mDevice);
134                 newIntent.putExtra(BluetoothDevice.EXTRA_ACCESS_REQUEST_TYPE,
135                         mRequestType);
136                 Log.d("Sending connection access acceptance intent.");
137                 abortBroadcast();
138                 c.sendBroadcast(newIntent,
139                         android.Manifest.permission.BLUETOOTH_ADMIN);
140             }
141         }
142     }
143 
144     /**
145      * Set autoConfirm flag to Value.
146      */
setAutoConfirm(boolean value)147     public synchronized void setAutoConfirm(boolean value) {
148         mAutoConfirm = value;
149     }
150 }
151