| /* |
| * Copyright (C) 2017 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.googlecode.android_scripting.facade.bluetooth; |
| |
| import android.bluetooth.BluetoothDevice; |
| import android.content.BroadcastReceiver; |
| import android.content.Context; |
| import android.content.Intent; |
| import android.os.Bundle; |
| |
| import com.googlecode.android_scripting.Log; |
| import com.googlecode.android_scripting.event.Event; |
| import com.googlecode.android_scripting.facade.EventFacade; |
| |
| public class BluetoothPairingHelper extends BroadcastReceiver { |
| private final EventFacade mEventFacade; |
| private static final int DEFAULT_TIMEOUT_MS = 5000; |
| private boolean mAutoConfirm = true; |
| |
| public BluetoothPairingHelper(EventFacade eventFacade) { |
| super(); |
| mEventFacade = eventFacade; |
| Log.d("Pairing helper created."); |
| } |
| |
| /** |
| * Confirms bluetooth connection/bonding requests. |
| */ |
| @Override |
| public void onReceive(Context c, Intent intent) { |
| String action = intent.getAction(); |
| Bundle result = new Bundle(); |
| Log.d("Bluetooth pairing intent received: " + action); |
| BluetoothDevice mDevice = intent.getParcelableExtra( |
| BluetoothDevice.EXTRA_DEVICE); |
| if (action.equals(BluetoothDevice.ACTION_PAIRING_REQUEST)) { |
| mDevice.setMessageAccessPermission(BluetoothDevice.ACCESS_ALLOWED); |
| mDevice.setPhonebookAccessPermission( |
| BluetoothDevice.ACCESS_ALLOWED); |
| int type = intent.getIntExtra( |
| BluetoothDevice.EXTRA_PAIRING_VARIANT, |
| BluetoothDevice.ERROR); |
| Log.d("Processing Action Paring Request with type " + type); |
| int pin = intent.getIntExtra(BluetoothDevice.EXTRA_PAIRING_KEY, 0); |
| String deviceAddress = mDevice.getAddress(); |
| result.putInt("Pin", pin); |
| result.putInt("PairingVariant", type); |
| result.putString("DeviceAddress", deviceAddress); |
| mEventFacade.postEvent("BluetoothActionPairingRequest", |
| result.clone()); |
| result.clear(); |
| if (type == BluetoothDevice.PAIRING_VARIANT_CONSENT) { |
| mDevice.setPairingConfirmation(true); |
| Log.d("Connection auto-confirmed by consent"); |
| // Abort the broadcast so Settings app doesn't get it. |
| abortBroadcast(); |
| } else if (type |
| == BluetoothDevice.PAIRING_VARIANT_PASSKEY_CONFIRMATION) { |
| if (mAutoConfirm) { |
| mDevice.setPairingConfirmation(true); |
| Log.d("Connection auto-confirmed"); |
| } else { |
| // Wait for confirmation |
| Event userConfirmEvent = null; |
| try { |
| userConfirmEvent = mEventFacade.eventWaitFor( |
| "BluetoothActionPairingRequestUserConfirm", |
| true, DEFAULT_TIMEOUT_MS); |
| } catch (InterruptedException e) { |
| Log.d("Connection interrupted"); |
| userConfirmEvent = null; |
| } |
| if (userConfirmEvent == null) { |
| Log.d("Null response received from test server or timeout"); |
| mDevice.setPairingConfirmation(false); |
| } else { |
| String userConfirmEventData = |
| (String) userConfirmEvent.getData(); |
| if (userConfirmEventData.equalsIgnoreCase("True")) { |
| mDevice.setPairingConfirmation(true); |
| Log.d("Connection confirmed"); |
| } else { |
| mDevice.setPairingConfirmation(false); |
| Log.d("Connection rejected"); |
| } |
| } |
| } |
| // Abort the broadcast so Settings app doesn't get it. |
| abortBroadcast(); |
| } |
| } else if (action.equals( |
| BluetoothDevice.ACTION_CONNECTION_ACCESS_REQUEST)) { |
| int type = intent.getIntExtra( |
| BluetoothDevice.EXTRA_ACCESS_REQUEST_TYPE, |
| BluetoothDevice.ERROR); |
| Log.d("Processing Action Connection Access Request type " + type); |
| if (type == BluetoothDevice.REQUEST_TYPE_MESSAGE_ACCESS |
| || type == BluetoothDevice.REQUEST_TYPE_PHONEBOOK_ACCESS |
| || type |
| == BluetoothDevice.REQUEST_TYPE_PROFILE_CONNECTION) { |
| Intent newIntent = |
| new Intent( |
| BluetoothDevice.ACTION_CONNECTION_ACCESS_REPLY); |
| String mReturnPackage = |
| intent.getStringExtra( |
| BluetoothDevice.EXTRA_PACKAGE_NAME); |
| String mReturnClass = |
| intent.getStringExtra(BluetoothDevice.EXTRA_CLASS_NAME); |
| int mRequestType = |
| intent.getIntExtra( |
| BluetoothDevice.EXTRA_ACCESS_REQUEST_TYPE, |
| BluetoothDevice.REQUEST_TYPE_MESSAGE_ACCESS); |
| if (mReturnPackage != null && mReturnClass != null) { |
| newIntent.setClassName(mReturnPackage, mReturnClass); |
| } |
| newIntent.putExtra(BluetoothDevice.EXTRA_CONNECTION_ACCESS_RESULT, |
| BluetoothDevice.CONNECTION_ACCESS_YES); |
| newIntent.putExtra(BluetoothDevice.EXTRA_ALWAYS_ALLOWED, true); |
| newIntent.putExtra(BluetoothDevice.EXTRA_DEVICE, mDevice); |
| newIntent.putExtra(BluetoothDevice.EXTRA_ACCESS_REQUEST_TYPE, |
| mRequestType); |
| Log.d("Sending connection access acceptance intent."); |
| abortBroadcast(); |
| c.sendBroadcast(newIntent, |
| android.Manifest.permission.BLUETOOTH_ADMIN); |
| } |
| } |
| } |
| |
| /** |
| * Set autoConfirm flag to Value. |
| */ |
| public synchronized void setAutoConfirm(boolean value) { |
| mAutoConfirm = value; |
| } |
| } |