1 /* 2 * Copyright (C) 2016 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.android.settings.bluetooth; 18 19 import android.annotation.Nullable; 20 import android.app.Activity; 21 import android.bluetooth.BluetoothDevice; 22 import android.content.BroadcastReceiver; 23 import android.content.Context; 24 import android.content.Intent; 25 import android.content.IntentFilter; 26 import android.os.Bundle; 27 import android.support.annotation.VisibleForTesting; 28 29 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS; 30 31 /** 32 * BluetoothPairingDialog asks the user to enter a PIN / Passkey / simple confirmation 33 * for pairing with a remote Bluetooth device. It is an activity that appears as a dialog. 34 */ 35 public class BluetoothPairingDialog extends Activity { 36 public static final String FRAGMENT_TAG = "bluetooth.pairing.fragment"; 37 38 private BluetoothPairingController mBluetoothPairingController; 39 private boolean mReceiverRegistered = false; 40 41 /** 42 * Dismiss the dialog if the bond state changes to bonded or none, 43 * or if pairing was canceled for {@link BluetoothPairingController#mDevice}. 44 */ 45 private final BroadcastReceiver mReceiver = new BroadcastReceiver() { 46 @Override 47 public void onReceive(Context context, Intent intent) { 48 String action = intent.getAction(); 49 if (BluetoothDevice.ACTION_BOND_STATE_CHANGED.equals(action)) { 50 int bondState = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, 51 BluetoothDevice.ERROR); 52 if (bondState == BluetoothDevice.BOND_BONDED || 53 bondState == BluetoothDevice.BOND_NONE) { 54 dismiss(); 55 } 56 } else if (BluetoothDevice.ACTION_PAIRING_CANCEL.equals(action)) { 57 BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); 58 if (device == null || mBluetoothPairingController.deviceEquals(device)) { 59 dismiss(); 60 } 61 } 62 } 63 }; 64 65 @Override onCreate(@ullable Bundle savedInstanceState)66 protected void onCreate(@Nullable Bundle savedInstanceState) { 67 super.onCreate(savedInstanceState); 68 69 getWindow().addPrivateFlags(PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS); 70 Intent intent = getIntent(); 71 mBluetoothPairingController = new BluetoothPairingController(intent, this); 72 // build the dialog fragment 73 boolean fragmentFound = true; 74 // check if the fragment has been preloaded 75 BluetoothPairingDialogFragment bluetoothFragment = 76 (BluetoothPairingDialogFragment) getFragmentManager().findFragmentByTag(FRAGMENT_TAG); 77 // dismiss the fragment if it is already used 78 if (bluetoothFragment != null && (bluetoothFragment.isPairingControllerSet() 79 || bluetoothFragment.isPairingDialogActivitySet())) { 80 bluetoothFragment.dismiss(); 81 bluetoothFragment = null; 82 } 83 // build a new fragment if it is null 84 if (bluetoothFragment == null) { 85 fragmentFound = false; 86 bluetoothFragment = new BluetoothPairingDialogFragment(); 87 } 88 bluetoothFragment.setPairingController(mBluetoothPairingController); 89 bluetoothFragment.setPairingDialogActivity(this); 90 // pass the fragment to the manager when it is created from scratch 91 if (!fragmentFound) { 92 bluetoothFragment.show(getFragmentManager(), FRAGMENT_TAG); 93 } 94 /* 95 * Leave this registered through pause/resume since we still want to 96 * finish the activity in the background if pairing is canceled. 97 */ 98 registerReceiver(mReceiver, new IntentFilter(BluetoothDevice.ACTION_PAIRING_CANCEL)); 99 registerReceiver(mReceiver, new IntentFilter(BluetoothDevice.ACTION_BOND_STATE_CHANGED)); 100 mReceiverRegistered = true; 101 } 102 103 @Override onDestroy()104 protected void onDestroy() { 105 super.onDestroy(); 106 if (mReceiverRegistered) { 107 mReceiverRegistered = false; 108 unregisterReceiver(mReceiver); 109 } 110 } 111 112 @VisibleForTesting dismiss()113 void dismiss() { 114 if (!isFinishing()) { 115 finish(); 116 } 117 } 118 } 119