165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane/* 265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * Copyright (C) 2014 The Android Open Source Project 365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * 465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * Licensed under the Apache License, Version 2.0 (the "License"); 565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * you may not use this file except in compliance with the License. 665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * You may obtain a copy of the License at 765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * 865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * http://www.apache.org/licenses/LICENSE-2.0 965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * 1065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * Unless required by applicable law or agreed to in writing, software 1165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * distributed under the License is distributed on an "AS IS" BASIS, 1265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * See the License for the specific language governing permissions and 1465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * limitations under the License. 1565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane */ 1665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 1765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lanepackage com.android.tv.settings.accessories; 1865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 1965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.app.Fragment; 2065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.bluetooth.BluetoothDevice; 2165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.content.BroadcastReceiver; 2265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.content.Context; 2365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.content.Intent; 2465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.content.IntentFilter; 2565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.graphics.drawable.ColorDrawable; 2665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.os.Bundle; 27eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantlerimport android.support.annotation.NonNull; 28eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantlerimport android.support.annotation.Nullable; 2965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.text.Html; 3065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.text.InputFilter; 3165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.text.InputFilter.LengthFilter; 326e995161147d9110d77ae1fe38b697e52891d3f2Tony Mantlerimport android.text.InputType; 3365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.util.Log; 3465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.view.KeyEvent; 3565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.view.LayoutInflater; 3665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.view.View; 3765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.view.ViewGroup; 386e995161147d9110d77ae1fe38b697e52891d3f2Tony Mantlerimport android.view.WindowManager; 39ec4d99d155402111d4baed27abae8d2e05d29f36Wally Yauimport android.view.inputmethod.EditorInfo; 4065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.widget.EditText; 4165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.widget.TextView; 42ec4d99d155402111d4baed27abae8d2e05d29f36Wally Yauimport android.widget.TextView.OnEditorActionListener; 4365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 446e995161147d9110d77ae1fe38b697e52891d3f2Tony Mantlerimport com.android.tv.settings.R; 456e995161147d9110d77ae1fe38b697e52891d3f2Tony Mantlerimport com.android.tv.settings.dialog.old.Action; 466e995161147d9110d77ae1fe38b697e52891d3f2Tony Mantlerimport com.android.tv.settings.dialog.old.ActionFragment; 476e995161147d9110d77ae1fe38b697e52891d3f2Tony Mantlerimport com.android.tv.settings.dialog.old.DialogActivity; 4865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport com.android.tv.settings.util.AccessibilityHelper; 4965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 5065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport java.util.ArrayList; 5165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport java.util.Locale; 5265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 5365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane/** 5465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * BluetoothPairingDialog asks the user to enter a PIN / Passkey / simple 5565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * confirmation for pairing with a remote Bluetooth device. 5665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane */ 5765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lanepublic class BluetoothPairingDialog extends DialogActivity { 5865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 5965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private static final String KEY_PAIR = "action_pair"; 6065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private static final String KEY_CANCEL = "action_cancel"; 6165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 62eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler private static final String TAG = "BluetoothPairingDialog"; 6365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private static final boolean DEBUG = false; 6465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 6565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private static final int BLUETOOTH_PIN_MAX_LENGTH = 16; 6665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private static final int BLUETOOTH_PASSKEY_MAX_LENGTH = 6; 6765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 6865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private BluetoothDevice mDevice; 6965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private int mType; 7065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private String mPairingKey; 71f245157027a91f27cb00e4f6c7dcbf9e02c92aeeWally Yau private boolean mPairingInProgress = false; 7265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 7365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane /** 7465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * Dismiss the dialog if the bond state changes to bonded or none, or if 7565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * pairing was canceled for {@link #mDevice}. 7665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane */ 7765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private final BroadcastReceiver mReceiver = new BroadcastReceiver() { 7865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane @Override 7965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public void onReceive(Context context, Intent intent) { 8065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane String action = intent.getAction(); 8165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (DEBUG) { 8265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane Log.d(TAG, "onReceive. Broadcast Intent = " + intent.toString()); 8365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 8465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (BluetoothDevice.ACTION_BOND_STATE_CHANGED.equals(action)) { 8565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane int bondState = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, 8665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane BluetoothDevice.ERROR); 8765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (bondState == BluetoothDevice.BOND_BONDED || 8865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane bondState == BluetoothDevice.BOND_NONE) { 8965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane dismiss(); 9065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 9165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } else if (BluetoothDevice.ACTION_PAIRING_CANCEL.equals(action)) { 9265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); 9365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (device == null || device.equals(mDevice)) { 9465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane dismiss(); 9565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 9665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 9765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 9865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane }; 9965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 10065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane @Override 10165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane protected void onCreate(Bundle savedInstanceState) { 10265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane super.onCreate(savedInstanceState); 10365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 104eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler final Intent intent = getIntent(); 10565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (!BluetoothDevice.ACTION_PAIRING_REQUEST.equals(intent.getAction())) { 10665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane Log.e(TAG, "Error: this activity may be started only with intent " + 10765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane BluetoothDevice.ACTION_PAIRING_REQUEST); 10865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane finish(); 10965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane return; 11065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 11165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 11265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); 11365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mType = intent.getIntExtra(BluetoothDevice.EXTRA_PAIRING_VARIANT, BluetoothDevice.ERROR); 11465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 11565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (DEBUG) { 11665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane Log.d(TAG, "Requested pairing Type = " + mType + " , Device = " + mDevice); 11765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 11865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 11965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane switch (mType) { 12065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane case BluetoothDevice.PAIRING_VARIANT_PIN: 12165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane case BluetoothDevice.PAIRING_VARIANT_PASSKEY: 12265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane createUserEntryDialog(); 12365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane break; 12465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 12565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane case BluetoothDevice.PAIRING_VARIANT_PASSKEY_CONFIRMATION: 12665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane int passkey = 12765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane intent.getIntExtra(BluetoothDevice.EXTRA_PAIRING_KEY, BluetoothDevice.ERROR); 12865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (passkey == BluetoothDevice.ERROR) { 12965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane Log.e(TAG, "Invalid Confirmation Passkey received, not showing any dialog"); 13065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane finish(); 13165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane return; 13265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 13365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mPairingKey = String.format(Locale.US, "%06d", passkey); 13465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane createConfirmationDialog(); 13565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane break; 13665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 13765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane case BluetoothDevice.PAIRING_VARIANT_CONSENT: 13865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane case BluetoothDevice.PAIRING_VARIANT_OOB_CONSENT: 13965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane createConfirmationDialog(); 14065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane break; 14165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 14265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane case BluetoothDevice.PAIRING_VARIANT_DISPLAY_PASSKEY: 14365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane case BluetoothDevice.PAIRING_VARIANT_DISPLAY_PIN: 14465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane int pairingKey = 14565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane intent.getIntExtra(BluetoothDevice.EXTRA_PAIRING_KEY, BluetoothDevice.ERROR); 14665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (pairingKey == BluetoothDevice.ERROR) { 14765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane Log.e(TAG, 14865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane "Invalid Confirmation Passkey or PIN received, not showing any dialog"); 14965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane finish(); 15065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane return; 15165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 15265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (mType == BluetoothDevice.PAIRING_VARIANT_DISPLAY_PASSKEY) { 15365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mPairingKey = String.format("%06d", pairingKey); 15465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } else { 15565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mPairingKey = String.format("%04d", pairingKey); 15665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 15765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane createConfirmationDialog(); 15865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane break; 15965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 16065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane default: 16165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane Log.e(TAG, "Incorrect pairing type received, not showing any dialog"); 16265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane finish(); 16365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane return; 16465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 16565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 16665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane // Fade out the old activity, and fade in the new activity. 16765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane overridePendingTransition(R.anim.fade_in, R.anim.fade_out); 16865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 169eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler // TODO: don't do this 170eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler final ViewGroup contentView = (ViewGroup) findViewById(android.R.id.content); 171eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler final View topLayout = contentView.getChildAt(0); 172eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler 17365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane // Set the activity background 174eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler final ColorDrawable bgDrawable = 175eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler new ColorDrawable(getColor(R.color.dialog_activity_background)); 176eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler bgDrawable.setAlpha(255); 177eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler topLayout.setBackground(bgDrawable); 17865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 17965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane // Make sure pairing wakes up day dream 18065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD | 18165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED | 18265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON | 18365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); 18465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 18565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 18665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane @Override 18765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane protected void onResume() { 18865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane super.onResume(); 18965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 19065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane IntentFilter filter = new IntentFilter(); 19165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane filter.addAction(BluetoothDevice.ACTION_PAIRING_CANCEL); 19265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane filter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED); 19365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane registerReceiver(mReceiver, filter); 19465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 19565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 19665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane @Override 19765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane protected void onPause() { 19865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane unregisterReceiver(mReceiver); 19965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 20065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane // Finish the activity if we get placed in the background and cancel pairing 201f245157027a91f27cb00e4f6c7dcbf9e02c92aeeWally Yau if (!mPairingInProgress) { 202f245157027a91f27cb00e4f6c7dcbf9e02c92aeeWally Yau cancelPairing(); 203f245157027a91f27cb00e4f6c7dcbf9e02c92aeeWally Yau } 20465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane dismiss(); 20565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 20665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane super.onPause(); 20765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 20865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 20965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane @Override 21065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public void onActionClicked(Action action) { 21165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane String key = action.getKey(); 21265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (KEY_PAIR.equals(key)) { 21365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane onPair(null); 21465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane dismiss(); 21565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } else if (KEY_CANCEL.equals(key)) { 21665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane cancelPairing(); 21765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 21865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 21965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 22065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane @Override 221eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler public boolean onKeyDown(int keyCode, @NonNull KeyEvent event) { 22265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (keyCode == KeyEvent.KEYCODE_BACK) { 22365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane cancelPairing(); 22465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 22565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane return super.onKeyDown(keyCode, event); 22665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 22765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 22865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private ArrayList<Action> getActions() { 229eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler ArrayList<Action> actions = new ArrayList<>(); 23065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 23165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane switch (mType) { 23265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane case BluetoothDevice.PAIRING_VARIANT_PASSKEY_CONFIRMATION: 23365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane case BluetoothDevice.PAIRING_VARIANT_CONSENT: 23465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane case BluetoothDevice.PAIRING_VARIANT_OOB_CONSENT: 23565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane actions.add(new Action.Builder() 23665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane .key(KEY_PAIR) 23765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane .title(getString(R.string.bluetooth_pair)) 23865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane .build()); 23965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 24065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane actions.add(new Action.Builder() 24165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane .key(KEY_CANCEL) 24265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane .title(getString(R.string.bluetooth_cancel)) 24365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane .build()); 24465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane break; 24565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane case BluetoothDevice.PAIRING_VARIANT_DISPLAY_PIN: 24665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane case BluetoothDevice.PAIRING_VARIANT_DISPLAY_PASSKEY: 24765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane actions.add(new Action.Builder() 24865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane .key(KEY_CANCEL) 24965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane .title(getString(R.string.bluetooth_cancel)) 25065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane .build()); 25165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane break; 25265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 25365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 25465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane return actions; 25565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 25665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 25765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private void dismiss() { 25865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane finish(); 25965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 26065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 26165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private void cancelPairing() { 26265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (DEBUG) { 26365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane Log.d(TAG, "cancelPairing"); 26465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 26565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mDevice.cancelPairingUserInput(); 26665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 26765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 26865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private void createUserEntryDialog() { 269eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler getFragmentManager().beginTransaction() 270eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler .replace(android.R.id.content, EntryDialogFragment.newInstance(mDevice, mType)) 271eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler .commit(); 27265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 27365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 27465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private void createConfirmationDialog() { 27565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane // Build a Dialog activity view, with Action Fragment 27665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 277eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler final ArrayList<Action> actions = getActions(); 27865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 279eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler final Fragment actionFragment = ActionFragment.newInstance(actions); 280eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler final Fragment contentFragment = 281eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler ConfirmationDialogFragment.newInstance(mDevice, mPairingKey, mType); 28265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 283eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler setContentAndActionFragments(contentFragment, actionFragment); 28465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 28565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 28665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private void onPair(String value) { 28765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (DEBUG) { 28865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane Log.d(TAG, "onPair: " + value); 28965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 29065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane switch (mType) { 29165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane case BluetoothDevice.PAIRING_VARIANT_PIN: 29265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane byte[] pinBytes = BluetoothDevice.convertPinToBytes(value); 29365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (pinBytes == null) { 29465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane return; 29565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 29665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mDevice.setPin(pinBytes); 297f245157027a91f27cb00e4f6c7dcbf9e02c92aeeWally Yau mPairingInProgress = true; 29865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane break; 29965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 30065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane case BluetoothDevice.PAIRING_VARIANT_PASSKEY: 301ec4d99d155402111d4baed27abae8d2e05d29f36Wally Yau try { 302ec4d99d155402111d4baed27abae8d2e05d29f36Wally Yau int passkey = Integer.parseInt(value); 303ec4d99d155402111d4baed27abae8d2e05d29f36Wally Yau mDevice.setPasskey(passkey); 304f245157027a91f27cb00e4f6c7dcbf9e02c92aeeWally Yau mPairingInProgress = true; 305ec4d99d155402111d4baed27abae8d2e05d29f36Wally Yau } catch (NumberFormatException e) { 306ec4d99d155402111d4baed27abae8d2e05d29f36Wally Yau Log.d(TAG, "pass key " + value + " is not an integer"); 307ec4d99d155402111d4baed27abae8d2e05d29f36Wally Yau } 30865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane break; 30965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 31065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane case BluetoothDevice.PAIRING_VARIANT_PASSKEY_CONFIRMATION: 31165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane case BluetoothDevice.PAIRING_VARIANT_CONSENT: 31265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mDevice.setPairingConfirmation(true); 313f245157027a91f27cb00e4f6c7dcbf9e02c92aeeWally Yau mPairingInProgress = true; 31465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane break; 31565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 31665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane case BluetoothDevice.PAIRING_VARIANT_DISPLAY_PASSKEY: 31765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane case BluetoothDevice.PAIRING_VARIANT_DISPLAY_PIN: 31865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane // Do nothing. 31965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane break; 32065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 32165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane case BluetoothDevice.PAIRING_VARIANT_OOB_CONSENT: 32265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mDevice.setRemoteOutOfBandData(); 323f245157027a91f27cb00e4f6c7dcbf9e02c92aeeWally Yau mPairingInProgress = true; 32465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane break; 32565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 32665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane default: 32765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane Log.e(TAG, "Incorrect pairing type received"); 32865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 32965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 33065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 331eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler public static class EntryDialogFragment extends Fragment { 332eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler 333eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler private static final String ARG_DEVICE = "ConfirmationDialogFragment.DEVICE"; 334eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler private static final String ARG_TYPE = "ConfirmationDialogFragment.TYPE"; 335eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler 336eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler private BluetoothDevice mDevice; 337eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler private int mType; 338eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler 339eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler public static EntryDialogFragment newInstance(BluetoothDevice device, int type) { 340eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler final EntryDialogFragment fragment = new EntryDialogFragment(); 341eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler final Bundle b = new Bundle(2); 342eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler fragment.setArguments(b); 343eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler b.putParcelable(ARG_DEVICE, device); 344eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler b.putInt(ARG_TYPE, type); 345eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler return fragment; 346eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler } 347eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler 348eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler @Override 349eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler public void onCreate(@Nullable Bundle savedInstanceState) { 350eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler super.onCreate(savedInstanceState); 351eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler final Bundle args = getArguments(); 352eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler mDevice = args.getParcelable(ARG_DEVICE); 353eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler mType = args.getInt(ARG_TYPE); 354eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler } 355eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler 356eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler @Override 357eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler public @Nullable View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, 358eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler Bundle savedInstanceState) { 359eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler final View v = inflater.inflate(R.layout.bt_pairing_passkey_entry, container, false); 360eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler 361eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler final TextView titleText = (TextView) v.findViewById(R.id.title_text); 362eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler final EditText textInput = (EditText) v.findViewById(R.id.text_input); 363eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler 364ec4d99d155402111d4baed27abae8d2e05d29f36Wally Yau textInput.setOnEditorActionListener(new OnEditorActionListener() { 365ec4d99d155402111d4baed27abae8d2e05d29f36Wally Yau @Override 366ec4d99d155402111d4baed27abae8d2e05d29f36Wally Yau public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { 367ec4d99d155402111d4baed27abae8d2e05d29f36Wally Yau String value = textInput.getText().toString(); 368ec4d99d155402111d4baed27abae8d2e05d29f36Wally Yau if (actionId == EditorInfo.IME_ACTION_NEXT || 369ec4d99d155402111d4baed27abae8d2e05d29f36Wally Yau (actionId == EditorInfo.IME_NULL && 370ec4d99d155402111d4baed27abae8d2e05d29f36Wally Yau event.getAction() == KeyEvent.ACTION_DOWN)) { 371ec4d99d155402111d4baed27abae8d2e05d29f36Wally Yau ((BluetoothPairingDialog)getActivity()).onPair(value); 372ec4d99d155402111d4baed27abae8d2e05d29f36Wally Yau } 373ec4d99d155402111d4baed27abae8d2e05d29f36Wally Yau return true; 374ec4d99d155402111d4baed27abae8d2e05d29f36Wally Yau } 375ec4d99d155402111d4baed27abae8d2e05d29f36Wally Yau }); 376ec4d99d155402111d4baed27abae8d2e05d29f36Wally Yau 377eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler final String instructions; 378eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler final int maxLength; 379eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler switch (mType) { 380eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler case BluetoothDevice.PAIRING_VARIANT_PIN: 381eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler instructions = getString(R.string.bluetooth_enter_pin_msg, mDevice.getName()); 382eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler final TextView instructionText = (TextView) v.findViewById(R.id.hint_text); 383eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler instructionText.setText(getString(R.string.bluetooth_pin_values_hint)); 384eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler // Maximum of 16 characters in a PIN 385eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler maxLength = BLUETOOTH_PIN_MAX_LENGTH; 386eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler textInput.setInputType(InputType.TYPE_CLASS_NUMBER); 387eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler break; 388eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler 389eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler case BluetoothDevice.PAIRING_VARIANT_PASSKEY: 390eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler instructions = getString(R.string.bluetooth_enter_passkey_msg, 391eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler mDevice.getName()); 392eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler // Maximum of 6 digits for passkey 393eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler maxLength = BLUETOOTH_PASSKEY_MAX_LENGTH; 394eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler textInput.setInputType(InputType.TYPE_CLASS_TEXT); 395eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler break; 396eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler 397eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler default: 398eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler throw new IllegalStateException("Incorrect pairing type for" + 399eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler " createPinEntryView: " + mType); 400eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler } 401eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler 402eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler titleText.setText(Html.fromHtml(instructions)); 403eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler 404eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler textInput.setFilters(new InputFilter[]{new LengthFilter(maxLength)}); 405eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler 406eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler return v; 407eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler } 408eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler } 409eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler 410eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler public static class ConfirmationDialogFragment extends Fragment { 411eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler 412eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler private static final String ARG_DEVICE = "ConfirmationDialogFragment.DEVICE"; 413eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler private static final String ARG_PAIRING_KEY = "ConfirmationDialogFragment.PAIRING_KEY"; 414eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler private static final String ARG_TYPE = "ConfirmationDialogFragment.TYPE"; 415eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler 416eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler private BluetoothDevice mDevice; 417eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler private String mPairingKey; 418eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler private int mType; 419eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler 420eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler public static ConfirmationDialogFragment newInstance(BluetoothDevice device, 421eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler String pairingKey, int type) { 422eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler final ConfirmationDialogFragment fragment = new ConfirmationDialogFragment(); 423eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler final Bundle b = new Bundle(3); 424eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler b.putParcelable(ARG_DEVICE, device); 425eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler b.putString(ARG_PAIRING_KEY, pairingKey); 426eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler b.putInt(ARG_TYPE, type); 427eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler fragment.setArguments(b); 428eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler return fragment; 429eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler } 430eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler 431eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler @Override 432eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler public void onCreate(@Nullable Bundle savedInstanceState) { 433eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler super.onCreate(savedInstanceState); 434eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler 435eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler final Bundle args = getArguments(); 436eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler 437eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler mDevice = args.getParcelable(ARG_DEVICE); 438eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler mPairingKey = args.getString(ARG_PAIRING_KEY); 439eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler mType = args.getInt(ARG_TYPE); 440eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler } 441eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler 442eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler @Override 443eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler public View onCreateView(LayoutInflater inflater, ViewGroup container, 444eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler Bundle savedInstanceState) { 445eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler final View v = inflater.inflate(R.layout.bt_pairing_passkey_display, container, false); 446eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler 447eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler final TextView titleText = (TextView) v.findViewById(R.id.title); 448eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler final TextView instructionText = (TextView) v.findViewById(R.id.pairing_instructions); 449eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler 450eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler titleText.setText(getString(R.string.bluetooth_pairing_request)); 451eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler 452eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler if (AccessibilityHelper.forceFocusableViews(getActivity())) { 453eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler titleText.setFocusable(true); 454eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler titleText.setFocusableInTouchMode(true); 455eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler instructionText.setFocusable(true); 456eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler instructionText.setFocusableInTouchMode(true); 457eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler } 458eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler 459eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler final String instructions; 460eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler 461eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler switch (mType) { 462eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler case BluetoothDevice.PAIRING_VARIANT_DISPLAY_PASSKEY: 463eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler case BluetoothDevice.PAIRING_VARIANT_DISPLAY_PIN: 464eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler instructions = getString(R.string.bluetooth_display_passkey_pin_msg, 465eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler mDevice.getName(), mPairingKey); 466eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler 467eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler // Since its only a notification, send an OK to the framework, 468eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler // indicating that the dialog has been displayed. 469eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler if (mType == BluetoothDevice.PAIRING_VARIANT_DISPLAY_PASSKEY) { 470eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler mDevice.setPairingConfirmation(true); 471eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler } else if (mType == BluetoothDevice.PAIRING_VARIANT_DISPLAY_PIN) { 472eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler byte[] pinBytes = BluetoothDevice.convertPinToBytes(mPairingKey); 473eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler mDevice.setPin(pinBytes); 474eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler } 475eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler break; 476eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler 477eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler case BluetoothDevice.PAIRING_VARIANT_PASSKEY_CONFIRMATION: 478eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler instructions = getString(R.string.bluetooth_confirm_passkey_msg, 479eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler mDevice.getName(), mPairingKey); 480eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler break; 481eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler 482eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler case BluetoothDevice.PAIRING_VARIANT_CONSENT: 483eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler case BluetoothDevice.PAIRING_VARIANT_OOB_CONSENT: 484eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler instructions = getString(R.string.bluetooth_incoming_pairing_msg, 485eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler mDevice.getName()); 486eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler 487eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler break; 488eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler default: 489eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler instructions = ""; 490eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler } 491eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler 492eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler instructionText.setText(Html.fromHtml(instructions)); 493eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler 494eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler return v; 495eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler } 496eae3ba62fcf7a7f159a9337bda08f38ce75b275eTony Mantler } 49765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane} 498