1afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project/*
2afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * Copyright (C) 2008 The Android Open Source Project
3afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project *
4afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
5afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * you may not use this file except in compliance with the License.
6afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * You may obtain a copy of the License at
7afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project *
8afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
9afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project *
10afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * Unless required by applicable law or agreed to in writing, software
11afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
12afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * See the License for the specific language governing permissions and
14afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * limitations under the License.
15afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project */
16afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
17afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectpackage com.android.settings.bluetooth;
18afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
19afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport android.bluetooth.BluetoothDevice;
20afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport android.content.BroadcastReceiver;
21afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport android.content.Context;
22afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport android.content.DialogInterface;
23afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport android.content.Intent;
24afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport android.content.IntentFilter;
25afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport android.os.Bundle;
26afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport android.text.Editable;
27ca9812a8521fcc483e821fd5a88ec421de0b8f66Jake Hambyimport android.text.Html;
28afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport android.text.InputFilter;
293a76bcaa83c15f96832f934e67e6f0190e72a3dcJaikumar Ganeshimport android.text.InputType;
30ca9812a8521fcc483e821fd5a88ec421de0b8f66Jake Hambyimport android.text.Spanned;
31afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport android.text.TextWatcher;
32afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport android.text.InputFilter.LengthFilter;
33afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport android.util.Log;
34afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport android.view.View;
35afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport android.widget.Button;
36ca9812a8521fcc483e821fd5a88ec421de0b8f66Jake Hambyimport android.widget.CheckBox;
37ca9812a8521fcc483e821fd5a88ec421de0b8f66Jake Hambyimport android.widget.CompoundButton;
38afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport android.widget.EditText;
39afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport android.widget.TextView;
40afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
41afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport com.android.internal.app.AlertActivity;
42afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport com.android.internal.app.AlertController;
43afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport com.android.settings.R;
44aaf8ffff79a73c71d3fb77a31950e344f4c7eab5jhtop.kimimport android.view.KeyEvent;
45afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
46ae8d5bdc5bfabb457135dbe9c30084bffdc16a7cFabrice Di Meglioimport java.util.Locale;
47ae8d5bdc5bfabb457135dbe9c30084bffdc16a7cFabrice Di Meglio
48afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project/**
493a76bcaa83c15f96832f934e67e6f0190e72a3dcJaikumar Ganesh * BluetoothPairingDialog asks the user to enter a PIN / Passkey / simple confirmation
503a76bcaa83c15f96832f934e67e6f0190e72a3dcJaikumar Ganesh * for pairing with a remote Bluetooth device. It is an activity that appears as a dialog.
51afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project */
52ca9812a8521fcc483e821fd5a88ec421de0b8f66Jake Hambypublic final class BluetoothPairingDialog extends AlertActivity implements
53ca9812a8521fcc483e821fd5a88ec421de0b8f66Jake Hamby        CompoundButton.OnCheckedChangeListener, DialogInterface.OnClickListener, TextWatcher {
543a76bcaa83c15f96832f934e67e6f0190e72a3dcJaikumar Ganesh    private static final String TAG = "BluetoothPairingDialog";
55afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
56e79f990490de49b39097433707c2bae6d8238330Jake Hamby    private static final int BLUETOOTH_PIN_MAX_LENGTH = 16;
57e79f990490de49b39097433707c2bae6d8238330Jake Hamby    private static final int BLUETOOTH_PASSKEY_MAX_LENGTH = 6;
58d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly    private BluetoothDevice mDevice;
593a76bcaa83c15f96832f934e67e6f0190e72a3dcJaikumar Ganesh    private int mType;
60da23ae88d110dce585b19581a180feefbb0be4c8Jaikumar Ganesh    private String mPairingKey;
613a76bcaa83c15f96832f934e67e6f0190e72a3dcJaikumar Ganesh    private EditText mPairingView;
62afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    private Button mOkButton;
63afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
64436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    /**
65436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby     * Dismiss the dialog if the bond state changes to bonded or none,
66436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby     * or if pairing was canceled for {@link #mDevice}.
67436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby     */
68436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
69afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        @Override
70afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        public void onReceive(Context context, Intent intent) {
71436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby            String action = intent.getAction();
72436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby            if (BluetoothDevice.ACTION_BOND_STATE_CHANGED.equals(action)) {
73435ad270b5f4e31e94a2bba204769660bbd4b3caJaikumar Ganesh                int bondState = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE,
74435ad270b5f4e31e94a2bba204769660bbd4b3caJaikumar Ganesh                                                   BluetoothDevice.ERROR);
75435ad270b5f4e31e94a2bba204769660bbd4b3caJaikumar Ganesh                if (bondState == BluetoothDevice.BOND_BONDED ||
76435ad270b5f4e31e94a2bba204769660bbd4b3caJaikumar Ganesh                        bondState == BluetoothDevice.BOND_NONE) {
77436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby                    dismiss();
78435ad270b5f4e31e94a2bba204769660bbd4b3caJaikumar Ganesh                }
79436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby            } else if (BluetoothDevice.ACTION_PAIRING_CANCEL.equals(action)) {
80435ad270b5f4e31e94a2bba204769660bbd4b3caJaikumar Ganesh                BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
81435ad270b5f4e31e94a2bba204769660bbd4b3caJaikumar Ganesh                if (device == null || device.equals(mDevice)) {
82436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby                    dismiss();
83435ad270b5f4e31e94a2bba204769660bbd4b3caJaikumar Ganesh                }
84afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            }
85afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        }
86afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    };
873a76bcaa83c15f96832f934e67e6f0190e72a3dcJaikumar Ganesh
88afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    @Override
89afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    protected void onCreate(Bundle savedInstanceState) {
90afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        super.onCreate(savedInstanceState);
91afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
92afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        Intent intent = getIntent();
9316cc86315d7a8e1f6a0f3083d0a810a7cb097832Nick Pelly        if (!intent.getAction().equals(BluetoothDevice.ACTION_PAIRING_REQUEST))
94afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        {
95436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby            Log.e(TAG, "Error: this activity may be started only with intent " +
9616cc86315d7a8e1f6a0f3083d0a810a7cb097832Nick Pelly                  BluetoothDevice.ACTION_PAIRING_REQUEST);
97afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            finish();
98436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby            return;
99afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        }
1003a76bcaa83c15f96832f934e67e6f0190e72a3dcJaikumar Ganesh
101436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby        LocalBluetoothManager manager = LocalBluetoothManager.getInstance(this);
102436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby        if (manager == null) {
103436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby            Log.e(TAG, "Error: BluetoothAdapter not supported by system");
104436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby            finish();
105436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby            return;
106436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby        }
107436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby        CachedBluetoothDeviceManager deviceManager = manager.getCachedDeviceManager();
108436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby
10916cc86315d7a8e1f6a0f3083d0a810a7cb097832Nick Pelly        mDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
11016cc86315d7a8e1f6a0f3083d0a810a7cb097832Nick Pelly        mType = intent.getIntExtra(BluetoothDevice.EXTRA_PAIRING_VARIANT, BluetoothDevice.ERROR);
111436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby
112436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby        switch (mType) {
113436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby            case BluetoothDevice.PAIRING_VARIANT_PIN:
114436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby            case BluetoothDevice.PAIRING_VARIANT_PASSKEY:
115436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby                createUserEntryDialog(deviceManager);
116436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby                break;
117436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby
118436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby            case BluetoothDevice.PAIRING_VARIANT_PASSKEY_CONFIRMATION:
119436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby                int passkey =
120436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby                    intent.getIntExtra(BluetoothDevice.EXTRA_PAIRING_KEY, BluetoothDevice.ERROR);
121436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby                if (passkey == BluetoothDevice.ERROR) {
122436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby                    Log.e(TAG, "Invalid Confirmation Passkey received, not showing any dialog");
123436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby                    return;
124436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby                }
125ae8d5bdc5bfabb457135dbe9c30084bffdc16a7cFabrice Di Meglio                mPairingKey = String.format(Locale.US, "%06d", passkey);
126436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby                createConfirmationDialog(deviceManager);
127436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby                break;
128436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby
129436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby            case BluetoothDevice.PAIRING_VARIANT_CONSENT:
130436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby            case BluetoothDevice.PAIRING_VARIANT_OOB_CONSENT:
131436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby                createConsentDialog(deviceManager);
132436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby                break;
133436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby
134436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby            case BluetoothDevice.PAIRING_VARIANT_DISPLAY_PASSKEY:
135436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby            case BluetoothDevice.PAIRING_VARIANT_DISPLAY_PIN:
136436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby                int pairingKey =
137436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby                    intent.getIntExtra(BluetoothDevice.EXTRA_PAIRING_KEY, BluetoothDevice.ERROR);
138436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby                if (pairingKey == BluetoothDevice.ERROR) {
139436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby                    Log.e(TAG, "Invalid Confirmation Passkey or PIN received, not showing any dialog");
140436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby                    return;
141436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby                }
142436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby                if (mType == BluetoothDevice.PAIRING_VARIANT_DISPLAY_PASSKEY) {
143436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby                    mPairingKey = String.format("%06d", pairingKey);
144436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby                } else {
145436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby                    mPairingKey = String.format("%04d", pairingKey);
146436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby                }
147436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby                createDisplayPasskeyOrPinDialog(deviceManager);
148436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby                break;
149436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby
150436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby            default:
151436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby                Log.e(TAG, "Incorrect pairing type received, not showing any dialog");
1523a76bcaa83c15f96832f934e67e6f0190e72a3dcJaikumar Ganesh        }
1533a76bcaa83c15f96832f934e67e6f0190e72a3dcJaikumar Ganesh
1543a76bcaa83c15f96832f934e67e6f0190e72a3dcJaikumar Ganesh        /*
1553a76bcaa83c15f96832f934e67e6f0190e72a3dcJaikumar Ganesh         * Leave this registered through pause/resume since we still want to
1563a76bcaa83c15f96832f934e67e6f0190e72a3dcJaikumar Ganesh         * finish the activity in the background if pairing is canceled.
1573a76bcaa83c15f96832f934e67e6f0190e72a3dcJaikumar Ganesh         */
15816cc86315d7a8e1f6a0f3083d0a810a7cb097832Nick Pelly        registerReceiver(mReceiver, new IntentFilter(BluetoothDevice.ACTION_PAIRING_CANCEL));
159435ad270b5f4e31e94a2bba204769660bbd4b3caJaikumar Ganesh        registerReceiver(mReceiver, new IntentFilter(BluetoothDevice.ACTION_BOND_STATE_CHANGED));
1603a76bcaa83c15f96832f934e67e6f0190e72a3dcJaikumar Ganesh    }
1613a76bcaa83c15f96832f934e67e6f0190e72a3dcJaikumar Ganesh
162436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    private void createUserEntryDialog(CachedBluetoothDeviceManager deviceManager) {
163afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        final AlertController.AlertParams p = mAlertParams;
164afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        p.mIconId = android.R.drawable.ic_dialog_info;
165435ad270b5f4e31e94a2bba204769660bbd4b3caJaikumar Ganesh        p.mTitle = getString(R.string.bluetooth_pairing_request);
166ca9812a8521fcc483e821fd5a88ec421de0b8f66Jake Hamby        p.mView = createPinEntryView(deviceManager.getName(mDevice));
167afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        p.mPositiveButtonText = getString(android.R.string.ok);
168afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        p.mPositiveButtonListener = this;
169afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        p.mNegativeButtonText = getString(android.R.string.cancel);
170afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        p.mNegativeButtonListener = this;
171afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        setupAlert();
1723a76bcaa83c15f96832f934e67e6f0190e72a3dcJaikumar Ganesh
173436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby        mOkButton = mAlert.getButton(BUTTON_POSITIVE);
174afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        mOkButton.setEnabled(false);
1753a76bcaa83c15f96832f934e67e6f0190e72a3dcJaikumar Ganesh    }
176afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
177ca9812a8521fcc483e821fd5a88ec421de0b8f66Jake Hamby    private View createPinEntryView(String deviceName) {
1783a76bcaa83c15f96832f934e67e6f0190e72a3dcJaikumar Ganesh        View view = getLayoutInflater().inflate(R.layout.bluetooth_pin_entry, null);
1793a76bcaa83c15f96832f934e67e6f0190e72a3dcJaikumar Ganesh        TextView messageView = (TextView) view.findViewById(R.id.message);
180ca9812a8521fcc483e821fd5a88ec421de0b8f66Jake Hamby        TextView messageView2 = (TextView) view.findViewById(R.id.message_below_pin);
181ca9812a8521fcc483e821fd5a88ec421de0b8f66Jake Hamby        CheckBox alphanumericPin = (CheckBox) view.findViewById(R.id.alphanumeric_pin);
1823a76bcaa83c15f96832f934e67e6f0190e72a3dcJaikumar Ganesh        mPairingView = (EditText) view.findViewById(R.id.text);
1833a76bcaa83c15f96832f934e67e6f0190e72a3dcJaikumar Ganesh        mPairingView.addTextChangedListener(this);
184ca9812a8521fcc483e821fd5a88ec421de0b8f66Jake Hamby        alphanumericPin.setOnCheckedChangeListener(this);
1853a76bcaa83c15f96832f934e67e6f0190e72a3dcJaikumar Ganesh
186ca9812a8521fcc483e821fd5a88ec421de0b8f66Jake Hamby        int messageId1;
187ca9812a8521fcc483e821fd5a88ec421de0b8f66Jake Hamby        int messageId2;
188ca9812a8521fcc483e821fd5a88ec421de0b8f66Jake Hamby        int maxLength;
189436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby        switch (mType) {
190436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby            case BluetoothDevice.PAIRING_VARIANT_PIN:
191ca9812a8521fcc483e821fd5a88ec421de0b8f66Jake Hamby                messageId1 = R.string.bluetooth_enter_pin_msg;
192ca9812a8521fcc483e821fd5a88ec421de0b8f66Jake Hamby                messageId2 = R.string.bluetooth_enter_pin_other_device;
193ca9812a8521fcc483e821fd5a88ec421de0b8f66Jake Hamby                // Maximum of 16 characters in a PIN
194ca9812a8521fcc483e821fd5a88ec421de0b8f66Jake Hamby                maxLength = BLUETOOTH_PIN_MAX_LENGTH;
195436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby                break;
196436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby
197436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby            case BluetoothDevice.PAIRING_VARIANT_PASSKEY:
198ca9812a8521fcc483e821fd5a88ec421de0b8f66Jake Hamby                messageId1 = R.string.bluetooth_enter_passkey_msg;
199ca9812a8521fcc483e821fd5a88ec421de0b8f66Jake Hamby                messageId2 = R.string.bluetooth_enter_passkey_other_device;
200436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby                // Maximum of 6 digits for passkey
201ca9812a8521fcc483e821fd5a88ec421de0b8f66Jake Hamby                maxLength = BLUETOOTH_PASSKEY_MAX_LENGTH;
202ca9812a8521fcc483e821fd5a88ec421de0b8f66Jake Hamby                alphanumericPin.setVisibility(View.GONE);
203436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby                break;
204436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby
205ca9812a8521fcc483e821fd5a88ec421de0b8f66Jake Hamby            default:
206ca9812a8521fcc483e821fd5a88ec421de0b8f66Jake Hamby                Log.e(TAG, "Incorrect pairing type for createPinEntryView: " + mType);
207ca9812a8521fcc483e821fd5a88ec421de0b8f66Jake Hamby                return null;
208ca9812a8521fcc483e821fd5a88ec421de0b8f66Jake Hamby        }
209ca9812a8521fcc483e821fd5a88ec421de0b8f66Jake Hamby
210ca9812a8521fcc483e821fd5a88ec421de0b8f66Jake Hamby        // Format the message string, then parse HTML style tags
211ca9812a8521fcc483e821fd5a88ec421de0b8f66Jake Hamby        String messageText = getString(messageId1, deviceName);
212ca9812a8521fcc483e821fd5a88ec421de0b8f66Jake Hamby        messageView.setText(Html.fromHtml(messageText));
213ca9812a8521fcc483e821fd5a88ec421de0b8f66Jake Hamby        messageView2.setText(messageId2);
214ca9812a8521fcc483e821fd5a88ec421de0b8f66Jake Hamby        mPairingView.setInputType(InputType.TYPE_CLASS_NUMBER);
215ca9812a8521fcc483e821fd5a88ec421de0b8f66Jake Hamby        mPairingView.setFilters(new InputFilter[] {
216ca9812a8521fcc483e821fd5a88ec421de0b8f66Jake Hamby                new LengthFilter(maxLength) });
217ca9812a8521fcc483e821fd5a88ec421de0b8f66Jake Hamby
218ca9812a8521fcc483e821fd5a88ec421de0b8f66Jake Hamby        return view;
219ca9812a8521fcc483e821fd5a88ec421de0b8f66Jake Hamby    }
220ca9812a8521fcc483e821fd5a88ec421de0b8f66Jake Hamby
221ca9812a8521fcc483e821fd5a88ec421de0b8f66Jake Hamby    private View createView(CachedBluetoothDeviceManager deviceManager) {
222ca9812a8521fcc483e821fd5a88ec421de0b8f66Jake Hamby        View view = getLayoutInflater().inflate(R.layout.bluetooth_pin_confirm, null);
223ca9812a8521fcc483e821fd5a88ec421de0b8f66Jake Hamby        String name = deviceManager.getName(mDevice);
224ca9812a8521fcc483e821fd5a88ec421de0b8f66Jake Hamby        TextView messageView = (TextView) view.findViewById(R.id.message);
225ca9812a8521fcc483e821fd5a88ec421de0b8f66Jake Hamby
226ca9812a8521fcc483e821fd5a88ec421de0b8f66Jake Hamby        String messageText; // formatted string containing HTML style tags
227ca9812a8521fcc483e821fd5a88ec421de0b8f66Jake Hamby        switch (mType) {
228436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby            case BluetoothDevice.PAIRING_VARIANT_PASSKEY_CONFIRMATION:
229ca9812a8521fcc483e821fd5a88ec421de0b8f66Jake Hamby                messageText = getString(R.string.bluetooth_confirm_passkey_msg,
230ca9812a8521fcc483e821fd5a88ec421de0b8f66Jake Hamby                        name, mPairingKey);
231436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby                break;
232436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby
233436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby            case BluetoothDevice.PAIRING_VARIANT_CONSENT:
234ca9812a8521fcc483e821fd5a88ec421de0b8f66Jake Hamby            case BluetoothDevice.PAIRING_VARIANT_OOB_CONSENT:
235ca9812a8521fcc483e821fd5a88ec421de0b8f66Jake Hamby                messageText = getString(R.string.bluetooth_incoming_pairing_msg, name);
236436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby                break;
237436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby
238436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby            case BluetoothDevice.PAIRING_VARIANT_DISPLAY_PASSKEY:
239436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby            case BluetoothDevice.PAIRING_VARIANT_DISPLAY_PIN:
240ca9812a8521fcc483e821fd5a88ec421de0b8f66Jake Hamby                messageText = getString(R.string.bluetooth_display_passkey_pin_msg, name,
241ca9812a8521fcc483e821fd5a88ec421de0b8f66Jake Hamby                        mPairingKey);
242436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby                break;
243436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby
244436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby            default:
245436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby                Log.e(TAG, "Incorrect pairing type received, not creating view");
246ca9812a8521fcc483e821fd5a88ec421de0b8f66Jake Hamby                return null;
2473a76bcaa83c15f96832f934e67e6f0190e72a3dcJaikumar Ganesh        }
248ca9812a8521fcc483e821fd5a88ec421de0b8f66Jake Hamby        messageView.setText(Html.fromHtml(messageText));
2493a76bcaa83c15f96832f934e67e6f0190e72a3dcJaikumar Ganesh        return view;
2503a76bcaa83c15f96832f934e67e6f0190e72a3dcJaikumar Ganesh    }
2513a76bcaa83c15f96832f934e67e6f0190e72a3dcJaikumar Ganesh
252436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    private void createConfirmationDialog(CachedBluetoothDeviceManager deviceManager) {
2533a76bcaa83c15f96832f934e67e6f0190e72a3dcJaikumar Ganesh        final AlertController.AlertParams p = mAlertParams;
2543a76bcaa83c15f96832f934e67e6f0190e72a3dcJaikumar Ganesh        p.mIconId = android.R.drawable.ic_dialog_info;
255435ad270b5f4e31e94a2bba204769660bbd4b3caJaikumar Ganesh        p.mTitle = getString(R.string.bluetooth_pairing_request);
256436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby        p.mView = createView(deviceManager);
257e41a4ca695db12308006fe1a6d061642b7d3f1a1Michael Chan        p.mPositiveButtonText = getString(R.string.bluetooth_pairing_accept);
2583a76bcaa83c15f96832f934e67e6f0190e72a3dcJaikumar Ganesh        p.mPositiveButtonListener = this;
259e41a4ca695db12308006fe1a6d061642b7d3f1a1Michael Chan        p.mNegativeButtonText = getString(R.string.bluetooth_pairing_decline);
2603a76bcaa83c15f96832f934e67e6f0190e72a3dcJaikumar Ganesh        p.mNegativeButtonListener = this;
2613a76bcaa83c15f96832f934e67e6f0190e72a3dcJaikumar Ganesh        setupAlert();
262afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    }
263afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
264436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    private void createConsentDialog(CachedBluetoothDeviceManager deviceManager) {
265435ad270b5f4e31e94a2bba204769660bbd4b3caJaikumar Ganesh        final AlertController.AlertParams p = mAlertParams;
266435ad270b5f4e31e94a2bba204769660bbd4b3caJaikumar Ganesh        p.mIconId = android.R.drawable.ic_dialog_info;
267435ad270b5f4e31e94a2bba204769660bbd4b3caJaikumar Ganesh        p.mTitle = getString(R.string.bluetooth_pairing_request);
268436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby        p.mView = createView(deviceManager);
269435ad270b5f4e31e94a2bba204769660bbd4b3caJaikumar Ganesh        p.mPositiveButtonText = getString(R.string.bluetooth_pairing_accept);
270435ad270b5f4e31e94a2bba204769660bbd4b3caJaikumar Ganesh        p.mPositiveButtonListener = this;
271435ad270b5f4e31e94a2bba204769660bbd4b3caJaikumar Ganesh        p.mNegativeButtonText = getString(R.string.bluetooth_pairing_decline);
272435ad270b5f4e31e94a2bba204769660bbd4b3caJaikumar Ganesh        p.mNegativeButtonListener = this;
273435ad270b5f4e31e94a2bba204769660bbd4b3caJaikumar Ganesh        setupAlert();
274afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    }
275afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
276436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    private void createDisplayPasskeyOrPinDialog(
277436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby            CachedBluetoothDeviceManager deviceManager) {
278435ad270b5f4e31e94a2bba204769660bbd4b3caJaikumar Ganesh        final AlertController.AlertParams p = mAlertParams;
279435ad270b5f4e31e94a2bba204769660bbd4b3caJaikumar Ganesh        p.mIconId = android.R.drawable.ic_dialog_info;
280435ad270b5f4e31e94a2bba204769660bbd4b3caJaikumar Ganesh        p.mTitle = getString(R.string.bluetooth_pairing_request);
281436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby        p.mView = createView(deviceManager);
282da23ae88d110dce585b19581a180feefbb0be4c8Jaikumar Ganesh        p.mNegativeButtonText = getString(android.R.string.cancel);
283da23ae88d110dce585b19581a180feefbb0be4c8Jaikumar Ganesh        p.mNegativeButtonListener = this;
284435ad270b5f4e31e94a2bba204769660bbd4b3caJaikumar Ganesh        setupAlert();
2853a76bcaa83c15f96832f934e67e6f0190e72a3dcJaikumar Ganesh
286435ad270b5f4e31e94a2bba204769660bbd4b3caJaikumar Ganesh        // Since its only a notification, send an OK to the framework,
287435ad270b5f4e31e94a2bba204769660bbd4b3caJaikumar Ganesh        // indicating that the dialog has been displayed.
288da23ae88d110dce585b19581a180feefbb0be4c8Jaikumar Ganesh        if (mType == BluetoothDevice.PAIRING_VARIANT_DISPLAY_PASSKEY) {
289da23ae88d110dce585b19581a180feefbb0be4c8Jaikumar Ganesh            mDevice.setPairingConfirmation(true);
290da23ae88d110dce585b19581a180feefbb0be4c8Jaikumar Ganesh        } else if (mType == BluetoothDevice.PAIRING_VARIANT_DISPLAY_PIN) {
291da23ae88d110dce585b19581a180feefbb0be4c8Jaikumar Ganesh            byte[] pinBytes = BluetoothDevice.convertPinToBytes(mPairingKey);
292da23ae88d110dce585b19581a180feefbb0be4c8Jaikumar Ganesh            mDevice.setPin(pinBytes);
293da23ae88d110dce585b19581a180feefbb0be4c8Jaikumar Ganesh        }
294afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    }
295afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
296afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    @Override
297afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    protected void onDestroy() {
298afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        super.onDestroy();
299afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        unregisterReceiver(mReceiver);
300afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    }
301afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
302afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    public void afterTextChanged(Editable s) {
3032affa6b28ddacc87f0f95f2ddd124b256ff61850jhtop.kim        if (mOkButton != null) {
3042affa6b28ddacc87f0f95f2ddd124b256ff61850jhtop.kim            mOkButton.setEnabled(s.length() > 0);
305afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        }
306afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    }
307afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
3083a76bcaa83c15f96832f934e67e6f0190e72a3dcJaikumar Ganesh    private void onPair(String value) {
309436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby        switch (mType) {
310436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby            case BluetoothDevice.PAIRING_VARIANT_PIN:
311436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby                byte[] pinBytes = BluetoothDevice.convertPinToBytes(value);
312436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby                if (pinBytes == null) {
313436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby                    return;
314436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby                }
315436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby                mDevice.setPin(pinBytes);
316436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby                break;
317436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby
318436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby            case BluetoothDevice.PAIRING_VARIANT_PASSKEY:
319436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby                int passkey = Integer.parseInt(value);
320436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby                mDevice.setPasskey(passkey);
321436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby                break;
322436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby
323436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby            case BluetoothDevice.PAIRING_VARIANT_PASSKEY_CONFIRMATION:
324436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby            case BluetoothDevice.PAIRING_VARIANT_CONSENT:
325436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby                mDevice.setPairingConfirmation(true);
326436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby                break;
327436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby
328436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby            case BluetoothDevice.PAIRING_VARIANT_DISPLAY_PASSKEY:
329436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby            case BluetoothDevice.PAIRING_VARIANT_DISPLAY_PIN:
330436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby                // Do nothing.
331436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby                break;
332436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby
333436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby            case BluetoothDevice.PAIRING_VARIANT_OOB_CONSENT:
334436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby                mDevice.setRemoteOutOfBandData();
335436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby                break;
336436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby
337436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby            default:
338436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby                Log.e(TAG, "Incorrect pairing type received");
339afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        }
340afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    }
341afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
342afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    private void onCancel() {
343cb6a3b3d9e39d63bbf10d947579989e44bcc0b98Jaikumar Ganesh        mDevice.cancelPairingUserInput();
344afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    }
345aaf8ffff79a73c71d3fb77a31950e344f4c7eab5jhtop.kim
346aaf8ffff79a73c71d3fb77a31950e344f4c7eab5jhtop.kim    public boolean onKeyDown(int keyCode, KeyEvent event) {
347aaf8ffff79a73c71d3fb77a31950e344f4c7eab5jhtop.kim        if (keyCode == KeyEvent.KEYCODE_BACK) {
348aaf8ffff79a73c71d3fb77a31950e344f4c7eab5jhtop.kim            onCancel();
349aaf8ffff79a73c71d3fb77a31950e344f4c7eab5jhtop.kim        }
350aaf8ffff79a73c71d3fb77a31950e344f4c7eab5jhtop.kim        return super.onKeyDown(keyCode,event);
351aaf8ffff79a73c71d3fb77a31950e344f4c7eab5jhtop.kim    }
3523a76bcaa83c15f96832f934e67e6f0190e72a3dcJaikumar Ganesh
353afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    public void onClick(DialogInterface dialog, int which) {
354afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        switch (which) {
355436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby            case BUTTON_POSITIVE:
356ca9812a8521fcc483e821fd5a88ec421de0b8f66Jake Hamby                if (mPairingView != null) {
357ca9812a8521fcc483e821fd5a88ec421de0b8f66Jake Hamby                    onPair(mPairingView.getText().toString());
358ca9812a8521fcc483e821fd5a88ec421de0b8f66Jake Hamby                } else {
359ca9812a8521fcc483e821fd5a88ec421de0b8f66Jake Hamby                    onPair(null);
360ca9812a8521fcc483e821fd5a88ec421de0b8f66Jake Hamby                }
361afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                break;
3623a76bcaa83c15f96832f934e67e6f0190e72a3dcJaikumar Ganesh
363436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby            case BUTTON_NEGATIVE:
364436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby            default:
365afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                onCancel();
366afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                break;
367afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        }
368afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    }
369afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
370afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    /* Not used */
371afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    public void beforeTextChanged(CharSequence s, int start, int count, int after) {
372afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    }
373afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
374afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    /* Not used */
375afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    public void onTextChanged(CharSequence s, int start, int before, int count) {
376afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    }
377afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
378ca9812a8521fcc483e821fd5a88ec421de0b8f66Jake Hamby    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
379ca9812a8521fcc483e821fd5a88ec421de0b8f66Jake Hamby        // change input type for soft keyboard to numeric or alphanumeric
380ca9812a8521fcc483e821fd5a88ec421de0b8f66Jake Hamby        if (isChecked) {
381ca9812a8521fcc483e821fd5a88ec421de0b8f66Jake Hamby            mPairingView.setInputType(InputType.TYPE_CLASS_TEXT);
382ca9812a8521fcc483e821fd5a88ec421de0b8f66Jake Hamby        } else {
383ca9812a8521fcc483e821fd5a88ec421de0b8f66Jake Hamby            mPairingView.setInputType(InputType.TYPE_CLASS_NUMBER);
384ca9812a8521fcc483e821fd5a88ec421de0b8f66Jake Hamby        }
385ca9812a8521fcc483e821fd5a88ec421de0b8f66Jake Hamby    }
386afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project}
387