1d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez/*
2d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez * Copyright (C) 2016 The Android Open Source Project
3d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez *
4d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez * Licensed under the Apache License, Version 2.0 (the "License");
5d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez * you may not use this file except in compliance with the License.
6d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez * You may obtain a copy of the License at
7d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez *
8d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez *      http://www.apache.org/licenses/LICENSE-2.0
9d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez *
10d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez * Unless required by applicable law or agreed to in writing, software
11d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez * distributed under the License is distributed on an "AS IS" BASIS,
12d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez * See the License for the specific language governing permissions and
14d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez * limitations under the License.
15d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez */
16d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinezpackage com.android.settings.bluetooth;
17d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez
18d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinezimport android.app.AlertDialog;
19d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinezimport android.app.Dialog;
20d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinezimport android.content.DialogInterface;
21d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinezimport android.content.DialogInterface.OnClickListener;
22d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinezimport android.os.Bundle;
23d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinezimport android.text.Editable;
24d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinezimport android.text.InputFilter;
25d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinezimport android.text.InputFilter.LengthFilter;
26d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinezimport android.text.InputType;
27d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinezimport android.text.TextWatcher;
28d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinezimport android.util.Log;
29d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinezimport android.view.View;
30d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinezimport android.widget.Button;
31d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinezimport android.widget.CheckBox;
32d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinezimport android.widget.EditText;
33d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinezimport android.widget.TextView;
34265d3c2a0c36251bf8a9f571d7239b6dd404d942Tamas Berghammerimport com.android.internal.logging.nano.MetricsProto.MetricsEvent;
35d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinezimport com.android.settings.R;
36d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinezimport com.android.settings.core.instrumentation.InstrumentedDialogFragment;
37d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez
38d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez/**
39d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez * A dialogFragment used by {@link BluetoothPairingDialog} to create an appropriately styled dialog
40d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez * for the bluetooth device.
41d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez */
42d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinezpublic class BluetoothPairingDialogFragment extends InstrumentedDialogFragment implements
43d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez        TextWatcher, OnClickListener {
44d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez
45d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez    private static final String TAG = "BTPairingDialogFragment";
46d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez
47d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez    private AlertDialog.Builder mBuilder;
48d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez    private AlertDialog mDialog;
49f492c28cc17e6def6d196e466256081662848be4Salvador Martinez    private BluetoothPairingController mPairingController;
502a67cf046511865107f78104b4296b8967d1cd5bJack He    private BluetoothPairingDialog mPairingDialogActivity;
51d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez    private EditText mPairingView;
52d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez    /**
53d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez     * The interface we expect a listener to implement. Typically this should be done by
54d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez     * the controller.
55d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez     */
56d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez    public interface BluetoothPairingDialogListener {
57d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez
58d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez        void onDialogNegativeClick(BluetoothPairingDialogFragment dialog);
59d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez
60d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez        void onDialogPositiveClick(BluetoothPairingDialogFragment dialog);
61d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez    }
62d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez
63d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez    @Override
64d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez    public Dialog onCreateDialog(Bundle savedInstanceState) {
652a67cf046511865107f78104b4296b8967d1cd5bJack He        if (!isPairingControllerSet()) {
66d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez            throw new IllegalStateException(
672a67cf046511865107f78104b4296b8967d1cd5bJack He                "Must call setPairingController() before showing dialog");
682a67cf046511865107f78104b4296b8967d1cd5bJack He        }
692a67cf046511865107f78104b4296b8967d1cd5bJack He        if (!isPairingDialogActivitySet()) {
702a67cf046511865107f78104b4296b8967d1cd5bJack He            throw new IllegalStateException(
712a67cf046511865107f78104b4296b8967d1cd5bJack He                "Must call setPairingDialogActivity() before showing dialog");
72d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez        }
73d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez        mBuilder = new AlertDialog.Builder(getActivity());
74d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez        mDialog = setupDialog();
75d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez        mDialog.setCanceledOnTouchOutside(false);
76d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez        return mDialog;
77d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez    }
78d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez
79d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez    @Override
80d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez    public void beforeTextChanged(CharSequence s, int start, int count, int after) {
81d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez    }
82d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez
83d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez    @Override
84d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez    public void onTextChanged(CharSequence s, int start, int before, int count) {
85d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez    }
86d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez
87d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez    @Override
88d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez    public void afterTextChanged(Editable s) {
89d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez        // enable the positive button when we detect potentially valid input
90d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez        Button positiveButton = mDialog.getButton(DialogInterface.BUTTON_POSITIVE);
91d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez        if (positiveButton != null) {
92d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez            positiveButton.setEnabled(mPairingController.isPasskeyValid(s));
93d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez        }
94d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez        // notify the controller about user input
95d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez        mPairingController.updateUserInput(s.toString());
96d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez    }
97d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez
98d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez    @Override
99d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez    public void onClick(DialogInterface dialog, int which) {
100d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez        if (which == DialogInterface.BUTTON_POSITIVE) {
101d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez            mPairingController.onDialogPositiveClick(this);
102d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez        } else if (which == DialogInterface.BUTTON_NEGATIVE) {
103d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez            mPairingController.onDialogNegativeClick(this);
104d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez        }
1052a67cf046511865107f78104b4296b8967d1cd5bJack He        mPairingDialogActivity.dismiss();
106d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez    }
107d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez
108d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez    @Override
109d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez    public int getMetricsCategory() {
110d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez        return MetricsEvent.BLUETOOTH_DIALOG_FRAGMENT;
111d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez    }
112d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez
113d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez    /**
114f492c28cc17e6def6d196e466256081662848be4Salvador Martinez     * Used in testing to get a reference to the dialog.
115f492c28cc17e6def6d196e466256081662848be4Salvador Martinez     * @return - The fragments current dialog
116f492c28cc17e6def6d196e466256081662848be4Salvador Martinez     */
117f492c28cc17e6def6d196e466256081662848be4Salvador Martinez    protected AlertDialog getmDialog() {
118f492c28cc17e6def6d196e466256081662848be4Salvador Martinez        return mDialog;
119f492c28cc17e6def6d196e466256081662848be4Salvador Martinez    }
120f492c28cc17e6def6d196e466256081662848be4Salvador Martinez
121f492c28cc17e6def6d196e466256081662848be4Salvador Martinez    /**
122d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez     * Sets the controller that the fragment should use. this method MUST be called
123d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez     * before you try to show the dialog or an error will be thrown. An implementation
124f492c28cc17e6def6d196e466256081662848be4Salvador Martinez     * of a pairing controller can be found at {@link BluetoothPairingController}. A
125f492c28cc17e6def6d196e466256081662848be4Salvador Martinez     * controller may not be substituted once it is assigned. Forcibly switching a
126f492c28cc17e6def6d196e466256081662848be4Salvador Martinez     * controller for a new one will lead to undefined behavior.
127d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez     */
1282a67cf046511865107f78104b4296b8967d1cd5bJack He    void setPairingController(BluetoothPairingController pairingController) {
1292a67cf046511865107f78104b4296b8967d1cd5bJack He        if (isPairingControllerSet()) {
130f492c28cc17e6def6d196e466256081662848be4Salvador Martinez            throw new IllegalStateException("The controller can only be set once. "
131f492c28cc17e6def6d196e466256081662848be4Salvador Martinez                    + "Forcibly replacing it will lead to undefined behavior");
132f492c28cc17e6def6d196e466256081662848be4Salvador Martinez        }
133d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez        mPairingController = pairingController;
134d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez    }
135d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez
136d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez    /**
1372a67cf046511865107f78104b4296b8967d1cd5bJack He     * Checks whether mPairingController is set
1382a67cf046511865107f78104b4296b8967d1cd5bJack He     * @return True when mPairingController is set, False otherwise
1392a67cf046511865107f78104b4296b8967d1cd5bJack He     */
1402a67cf046511865107f78104b4296b8967d1cd5bJack He    boolean isPairingControllerSet() {
1412a67cf046511865107f78104b4296b8967d1cd5bJack He        return mPairingController != null;
1422a67cf046511865107f78104b4296b8967d1cd5bJack He    }
1432a67cf046511865107f78104b4296b8967d1cd5bJack He
1442a67cf046511865107f78104b4296b8967d1cd5bJack He    /**
1452a67cf046511865107f78104b4296b8967d1cd5bJack He     * Sets the BluetoothPairingDialog activity that started this fragment
1462a67cf046511865107f78104b4296b8967d1cd5bJack He     * @param pairingDialogActivity The pairing dialog activty that started this fragment
1472a67cf046511865107f78104b4296b8967d1cd5bJack He     */
1482a67cf046511865107f78104b4296b8967d1cd5bJack He    void setPairingDialogActivity(BluetoothPairingDialog pairingDialogActivity) {
1492a67cf046511865107f78104b4296b8967d1cd5bJack He        if (isPairingDialogActivitySet()) {
1502a67cf046511865107f78104b4296b8967d1cd5bJack He            throw new IllegalStateException("The pairing dialog activity can only be set once");
1512a67cf046511865107f78104b4296b8967d1cd5bJack He        }
1522a67cf046511865107f78104b4296b8967d1cd5bJack He        mPairingDialogActivity = pairingDialogActivity;
1532a67cf046511865107f78104b4296b8967d1cd5bJack He    }
1542a67cf046511865107f78104b4296b8967d1cd5bJack He
1552a67cf046511865107f78104b4296b8967d1cd5bJack He    /**
1562a67cf046511865107f78104b4296b8967d1cd5bJack He     * Checks whether mPairingDialogActivity is set
1572a67cf046511865107f78104b4296b8967d1cd5bJack He     * @return True when mPairingDialogActivity is set, False otherwise
1582a67cf046511865107f78104b4296b8967d1cd5bJack He     */
1592a67cf046511865107f78104b4296b8967d1cd5bJack He    boolean isPairingDialogActivitySet() {
1602a67cf046511865107f78104b4296b8967d1cd5bJack He        return mPairingDialogActivity != null;
1612a67cf046511865107f78104b4296b8967d1cd5bJack He    }
1622a67cf046511865107f78104b4296b8967d1cd5bJack He
1632a67cf046511865107f78104b4296b8967d1cd5bJack He    /**
164d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez     * Creates the appropriate type of dialog and returns it.
165d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez     */
166d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez    private AlertDialog setupDialog() {
167d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez        AlertDialog dialog;
168d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez        switch (mPairingController.getDialogType()) {
169d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez            case BluetoothPairingController.USER_ENTRY_DIALOG:
170d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez                dialog = createUserEntryDialog();
171d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez                break;
172d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez            case BluetoothPairingController.CONFIRMATION_DIALOG:
173d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez                dialog = createConsentDialog();
174d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez                break;
175d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez            case BluetoothPairingController.DISPLAY_PASSKEY_DIALOG:
176d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez                dialog = createDisplayPasskeyOrPinDialog();
177d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez                break;
178d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez            default:
179d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez                dialog = null;
180d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez                Log.e(TAG, "Incorrect pairing type received, not showing any dialog");
181d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez        }
182d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez        return dialog;
183d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez    }
184d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez
185d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez    /**
186d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez     * Returns a dialog with UI elements that allow a user to provide input.
187d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez     */
188d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez    private AlertDialog createUserEntryDialog() {
189d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez        mBuilder.setTitle(getString(R.string.bluetooth_pairing_request,
190d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez                mPairingController.getDeviceName()));
191d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez        mBuilder.setView(createPinEntryView());
192d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez        mBuilder.setPositiveButton(getString(android.R.string.ok), this);
193d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez        mBuilder.setNegativeButton(getString(android.R.string.cancel), this);
194d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez        AlertDialog dialog = mBuilder.create();
195f492c28cc17e6def6d196e466256081662848be4Salvador Martinez        dialog.setOnShowListener(d -> mDialog.getButton(Dialog.BUTTON_POSITIVE).setEnabled(false));
196d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez        return dialog;
197d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez    }
198d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez
199d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez    /**
200d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez     * Creates the custom view with UI elements for user input.
201d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez     */
202d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez    private View createPinEntryView() {
203d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez        View view = getActivity().getLayoutInflater().inflate(R.layout.bluetooth_pin_entry, null);
204d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez        TextView messageViewCaptionHint = (TextView) view.findViewById(R.id.pin_values_hint);
205d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez        TextView messageView2 = (TextView) view.findViewById(R.id.message_below_pin);
206d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez        CheckBox alphanumericPin = (CheckBox) view.findViewById(R.id.alphanumeric_pin);
207d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez        CheckBox contactSharing = (CheckBox) view.findViewById(
208d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez                R.id.phonebook_sharing_message_entry_pin);
209d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez        contactSharing.setText(getString(R.string.bluetooth_pairing_shares_phonebook,
210d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez                mPairingController.getDeviceName()));
211d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez        EditText pairingView = (EditText) view.findViewById(R.id.text);
212d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez
213d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez        contactSharing.setVisibility(mPairingController.isProfileReady()
214d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez                ? View.GONE : View.VISIBLE);
215d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez        contactSharing.setOnCheckedChangeListener(mPairingController);
216d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez        contactSharing.setChecked(mPairingController.getContactSharingState());
217d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez
218d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez        mPairingView = pairingView;
219d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez
220f492c28cc17e6def6d196e466256081662848be4Salvador Martinez        pairingView.setInputType(InputType.TYPE_CLASS_NUMBER);
221d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez        pairingView.addTextChangedListener(this);
222d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez        alphanumericPin.setOnCheckedChangeListener((buttonView, isChecked) -> {
223d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez            // change input type for soft keyboard to numeric or alphanumeric
224d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez            if (isChecked) {
225d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez                mPairingView.setInputType(InputType.TYPE_CLASS_TEXT);
226d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez            } else {
227d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez                mPairingView.setInputType(InputType.TYPE_CLASS_NUMBER);
228d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez            }
229d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez        });
230d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez
231f492c28cc17e6def6d196e466256081662848be4Salvador Martinez        int messageId = mPairingController.getDeviceVariantMessageId();
232f492c28cc17e6def6d196e466256081662848be4Salvador Martinez        int messageIdHint = mPairingController.getDeviceVariantMessageHintId();
233d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez        int maxLength = mPairingController.getDeviceMaxPasskeyLength();
234d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez        alphanumericPin.setVisibility(mPairingController.pairingCodeIsAlphanumeric()
235d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez                ? View.VISIBLE : View.GONE);
236f492c28cc17e6def6d196e466256081662848be4Salvador Martinez        if (messageId != BluetoothPairingController.INVALID_DIALOG_TYPE) {
237f492c28cc17e6def6d196e466256081662848be4Salvador Martinez            messageView2.setText(messageId);
238f492c28cc17e6def6d196e466256081662848be4Salvador Martinez        } else {
239f492c28cc17e6def6d196e466256081662848be4Salvador Martinez            messageView2.setVisibility(View.GONE);
240f492c28cc17e6def6d196e466256081662848be4Salvador Martinez        }
241f492c28cc17e6def6d196e466256081662848be4Salvador Martinez        if (messageIdHint != BluetoothPairingController.INVALID_DIALOG_TYPE) {
242f492c28cc17e6def6d196e466256081662848be4Salvador Martinez            messageViewCaptionHint.setText(messageIdHint);
243f492c28cc17e6def6d196e466256081662848be4Salvador Martinez        } else {
244f492c28cc17e6def6d196e466256081662848be4Salvador Martinez            messageViewCaptionHint.setVisibility(View.GONE);
245f492c28cc17e6def6d196e466256081662848be4Salvador Martinez        }
246d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez        pairingView.setFilters(new InputFilter[]{
247d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez                new LengthFilter(maxLength)});
248d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez
249d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez        return view;
250d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez    }
251d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez
252d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez    /**
253d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez     * Creates a dialog with UI elements that allow the user to confirm a pairing request.
254d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez     */
255d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez    private AlertDialog createConfirmationDialog() {
256d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez        mBuilder.setTitle(getString(R.string.bluetooth_pairing_request,
257d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez                mPairingController.getDeviceName()));
258d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez        mBuilder.setView(createView());
259f492c28cc17e6def6d196e466256081662848be4Salvador Martinez        mBuilder.setPositiveButton(getString(R.string.bluetooth_pairing_accept), this);
260f492c28cc17e6def6d196e466256081662848be4Salvador Martinez        mBuilder.setNegativeButton(getString(R.string.bluetooth_pairing_decline), this);
261d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez        AlertDialog dialog = mBuilder.create();
262d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez        return dialog;
263d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez    }
264d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez
265d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez    /**
266d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez     * Creates a dialog with UI elements that allow the user to consent to a pairing request.
267d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez     */
268d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez    private AlertDialog createConsentDialog() {
269d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez        return createConfirmationDialog();
270d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez    }
271d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez
272d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez    /**
273d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez     * Creates a dialog that informs users of a pairing request and shows them the passkey/pin
274d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez     * of the device.
275d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez     */
276d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez    private AlertDialog createDisplayPasskeyOrPinDialog() {
277d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez        mBuilder.setTitle(getString(R.string.bluetooth_pairing_request,
278d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez                mPairingController.getDeviceName()));
279d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez        mBuilder.setView(createView());
280d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez        mBuilder.setNegativeButton(getString(android.R.string.cancel), this);
281d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez        AlertDialog dialog = mBuilder.create();
282d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez
283d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez        // Tell the controller the dialog has been created.
284d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez        mPairingController.notifyDialogDisplayed();
285d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez
286d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez        return dialog;
287d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez    }
288d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez
289d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez    /**
290d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez     * Creates a custom view for dialogs which need to show users additional information but do
291d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez     * not require user input.
292d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez     */
293d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez    private View createView() {
294d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez        View view = getActivity().getLayoutInflater().inflate(R.layout.bluetooth_pin_confirm, null);
295d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez        TextView pairingViewCaption = (TextView) view.findViewById(R.id.pairing_caption);
296d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez        TextView pairingViewContent = (TextView) view.findViewById(R.id.pairing_subhead);
297d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez        TextView messagePairing = (TextView) view.findViewById(R.id.pairing_code_message);
298d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez        CheckBox contactSharing = (CheckBox) view.findViewById(
299d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez                R.id.phonebook_sharing_message_confirm_pin);
300d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez        contactSharing.setText(getString(R.string.bluetooth_pairing_shares_phonebook,
301d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez                mPairingController.getDeviceName()));
302d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez
303d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez        contactSharing.setVisibility(
304d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez                mPairingController.isProfileReady() ? View.GONE : View.VISIBLE);
305d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez        contactSharing.setChecked(mPairingController.getContactSharingState());
306d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez        contactSharing.setOnCheckedChangeListener(mPairingController);
307d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez
308d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez        messagePairing.setVisibility(mPairingController.isDisplayPairingKeyVariant()
309d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez                ? View.VISIBLE : View.GONE);
310d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez        if (mPairingController.hasPairingContent()) {
311d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez            pairingViewCaption.setVisibility(View.VISIBLE);
312d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez            pairingViewContent.setVisibility(View.VISIBLE);
313d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez            pairingViewContent.setText(mPairingController.getPairingContent());
314d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez        }
315d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez        return view;
316d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez    }
317d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez
318d98d0837d85d11b29967c924638a1f0af6e08e24Salvador Martinez}
319