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