1e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan/*
2e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan * Copyright (C) 2009 The Android Open Source Project
3e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan *
4e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan * Licensed under the Apache License, Version 2.0 (the "License");
5e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan * you may not use this file except in compliance with the License.
6e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan * You may obtain a copy of the License at
7e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan *
8e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan *      http://www.apache.org/licenses/LICENSE-2.0
9e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan *
10e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan * Unless required by applicable law or agreed to in writing, software
11e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan * distributed under the License is distributed on an "AS IS" BASIS,
12e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan * See the License for the specific language governing permissions and
14e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan * limitations under the License.
15e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan */
16e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan
17e1089ad33896f4fe5b75e773813367d700773b6fMichael Chanpackage com.android.settings.bluetooth;
18e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan
190cf1298a44d8fa062030e6e6e0d7f27637c48961Svet Ganovimport android.annotation.NonNull;
20834e5993e4f2f34d5aceb3196601b30231d00b07Michael Chanimport android.app.Activity;
21a0de1dcd1960181d9d8fd2e44f19dead16021e2bMichael Chanimport android.app.AlertDialog;
22e1089ad33896f4fe5b75e773813367d700773b6fMichael Chanimport android.bluetooth.BluetoothAdapter;
23e1089ad33896f4fe5b75e773813367d700773b6fMichael Chanimport android.bluetooth.BluetoothDevice;
24e1089ad33896f4fe5b75e773813367d700773b6fMichael Chanimport android.content.BroadcastReceiver;
25e1089ad33896f4fe5b75e773813367d700773b6fMichael Chanimport android.content.Context;
26e1089ad33896f4fe5b75e773813367d700773b6fMichael Chanimport android.content.DialogInterface;
27e1089ad33896f4fe5b75e773813367d700773b6fMichael Chanimport android.content.Intent;
28e1089ad33896f4fe5b75e773813367d700773b6fMichael Chanimport android.content.IntentFilter;
290cf1298a44d8fa062030e6e6e0d7f27637c48961Svet Ganovimport android.content.pm.ApplicationInfo;
300cf1298a44d8fa062030e6e6e0d7f27637c48961Svet Ganovimport android.content.pm.PackageManager;
31e1089ad33896f4fe5b75e773813367d700773b6fMichael Chanimport android.os.Bundle;
320cf1298a44d8fa062030e6e6e0d7f27637c48961Svet Ganovimport android.text.TextUtils;
33e1089ad33896f4fe5b75e773813367d700773b6fMichael Chanimport android.util.Log;
34e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan
35f2982a9ba19340b474bafb6b0bf5832673984e0dJason Monkimport com.android.settings.R;
36f2982a9ba19340b474bafb6b0bf5832673984e0dJason Monkimport com.android.settingslib.bluetooth.BluetoothDiscoverableTimeoutReceiver;
37f2982a9ba19340b474bafb6b0bf5832673984e0dJason Monkimport com.android.settingslib.bluetooth.LocalBluetoothAdapter;
38f2982a9ba19340b474bafb6b0bf5832673984e0dJason Monkimport com.android.settingslib.bluetooth.LocalBluetoothManager;
39f2982a9ba19340b474bafb6b0bf5832673984e0dJason Monk
40e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan/**
4117d2124c1ccb1bd46393f70252d06d866646e97dWei Wang * RequestPermissionActivity asks the user whether to enable discovery. This is
4217d2124c1ccb1bd46393f70252d06d866646e97dWei Wang * usually started by an application wanted to start bluetooth and or discovery
43e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan */
44a0de1dcd1960181d9d8fd2e44f19dead16021e2bMichael Chanpublic class RequestPermissionActivity extends Activity implements
45e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan        DialogInterface.OnClickListener {
46e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan    // Command line to test this
47e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan    // adb shell am start -a android.bluetooth.adapter.action.REQUEST_ENABLE
48e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan    // adb shell am start -a android.bluetooth.adapter.action.REQUEST_DISCOVERABLE
49b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov    // adb shell am start -a android.bluetooth.adapter.action.REQUEST_DISABLE
50e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan
51e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan    private static final String TAG = "RequestPermissionActivity";
52e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan
53d955af8461b845a1ce4f9beba9decfc2cffb0966Jaikumar Ganesh    private static final int MAX_DISCOVERABLE_TIMEOUT = 3600; // 1 hr
54e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan
55b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov    static final int REQUEST_ENABLE = 1;
56b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov    static final int REQUEST_ENABLE_DISCOVERABLE = 2;
57b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov    static final int REQUEST_DISABLE = 3;
58e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan
59436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    private LocalBluetoothAdapter mLocalAdapter;
60e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan
61e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan    private int mTimeout = BluetoothDiscoverableEnabler.DEFAULT_DISCOVERABLE_TIMEOUT;
62e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan
63b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov    private int mRequest;
64e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan
65436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    private AlertDialog mDialog;
66a0de1dcd1960181d9d8fd2e44f19dead16021e2bMichael Chan
67b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov    private BroadcastReceiver mReceiver;
68e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan
690cf1298a44d8fa062030e6e6e0d7f27637c48961Svet Ganov    private @NonNull CharSequence mAppLabel;
700cf1298a44d8fa062030e6e6e0d7f27637c48961Svet Ganov
71e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan    @Override
72e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan    protected void onCreate(Bundle savedInstanceState) {
73e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan        super.onCreate(savedInstanceState);
74e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan
75b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov        setResult(Activity.RESULT_CANCELED);
76b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov
77436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby        // Note: initializes mLocalAdapter and returns true on error
78e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan        if (parseIntent()) {
79e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan            finish();
80e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan            return;
81e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan        }
82e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan
83436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby        int btState = mLocalAdapter.getState();
84e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan
85b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov        if (mRequest == REQUEST_DISABLE) {
86b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov            switch (btState) {
87b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov                case BluetoothAdapter.STATE_OFF:
88b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov                case BluetoothAdapter.STATE_TURNING_OFF: {
89eb56b9ccb8fa70a6c567d0bcd02f821e4de4bf7bWei Wang                    proceedAndFinish();
90b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov                } break;
91b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov
92b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov                case BluetoothAdapter.STATE_ON:
93b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov                case BluetoothAdapter.STATE_TURNING_ON: {
94b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov                    Intent intent = new Intent(this, RequestPermissionHelperActivity.class);
950cf1298a44d8fa062030e6e6e0d7f27637c48961Svet Ganov                    intent.putExtra(RequestPermissionHelperActivity.EXTRA_APP_LABEL, mAppLabel);
96b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov                    intent.setAction(RequestPermissionHelperActivity
97b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov                                .ACTION_INTERNAL_REQUEST_BT_OFF);
980cf1298a44d8fa062030e6e6e0d7f27637c48961Svet Ganov
99b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov                    startActivityForResult(intent, 0);
100b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov                } break;
101b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov
102b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov                default: {
103b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov                    Log.e(TAG, "Unknown adapter state: " + btState);
104b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov                    cancelAndFinish();
105b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov                } break;
106b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov            }
107b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov        } else {
108b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov            switch (btState) {
109b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov                case BluetoothAdapter.STATE_OFF:
110b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov                case BluetoothAdapter.STATE_TURNING_OFF:
111b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov                case BluetoothAdapter.STATE_TURNING_ON: {
112b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov                    /*
113b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov                     * Strictly speaking STATE_TURNING_ON belong with STATE_ON;
114b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov                     * however, BT may not be ready when the user clicks yes and we
115b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov                     * would fail to turn on discovery mode. By kicking this to the
116b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov                     * RequestPermissionHelperActivity, this class will handle that
117b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov                     * case via the broadcast receiver.
118b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov                     */
119b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov
120b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov                    /*
121b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov                     * Start the helper activity to:
122b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov                     * 1) ask the user about enabling bt AND discovery
123b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov                     * 2) enable BT upon confirmation
124b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov                     */
125b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov                    Intent intent = new Intent(this, RequestPermissionHelperActivity.class);
126b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov                    intent.setAction(RequestPermissionHelperActivity.ACTION_INTERNAL_REQUEST_BT_ON);
1270cf1298a44d8fa062030e6e6e0d7f27637c48961Svet Ganov                    intent.putExtra(RequestPermissionHelperActivity.EXTRA_APP_LABEL, mAppLabel);
128b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov                    if (mRequest == REQUEST_ENABLE_DISCOVERABLE) {
129b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov                        intent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, mTimeout);
130b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov                    }
131b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov                    startActivityForResult(intent, 0);
132b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov                } break;
133b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov
134b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov                case BluetoothAdapter.STATE_ON: {
135b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov                    if (mRequest == REQUEST_ENABLE) {
136b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov                        // Nothing to do. Already enabled.
137b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov                        proceedAndFinish();
138b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov                    } else {
139b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov                        // Ask the user about enabling discovery mode
140b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov                        createDialog();
141b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov                    }
142b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov                } break;
143b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov
144b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov                default: {
145b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov                    Log.e(TAG, "Unknown adapter state: " + btState);
146b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov                    cancelAndFinish();
147b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov                } break;
148b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov            }
149e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan        }
150e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan    }
151e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan
152e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan    private void createDialog() {
153b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov        if (getResources().getBoolean(R.bool.auto_confirm_bluetooth_activation_dialog)) {
154b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov            onClick(null, DialogInterface.BUTTON_POSITIVE);
155b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov            return;
156b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov        }
157b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov
158a0de1dcd1960181d9d8fd2e44f19dead16021e2bMichael Chan        AlertDialog.Builder builder = new AlertDialog.Builder(this);
159e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan
160b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov        // Non-null receiver means we are toggling
161b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov        if (mReceiver != null) {
162b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov            switch (mRequest) {
163b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov                case REQUEST_ENABLE:
164b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov                case REQUEST_ENABLE_DISCOVERABLE: {
165b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov                    builder.setMessage(getString(R.string.bluetooth_turning_on));
166b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov                } break;
167b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov
168b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov                default: {
169b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov                    builder.setMessage(getString(R.string.bluetooth_turning_off));
170b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov                } break;
171b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov            }
172a0de1dcd1960181d9d8fd2e44f19dead16021e2bMichael Chan            builder.setCancelable(false);
17317d2124c1ccb1bd46393f70252d06d866646e97dWei Wang        } else {
174e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan            // Ask the user whether to turn on discovery mode or not
1751b0489cb3eb051b2cf18aa2cb3110ff904c9ebe8Chris Wren            // For lasting discoverable mode there is a different message
1761b0489cb3eb051b2cf18aa2cb3110ff904c9ebe8Chris Wren            if (mTimeout == BluetoothDiscoverableEnabler.DISCOVERABLE_TIMEOUT_NEVER) {
1770cf1298a44d8fa062030e6e6e0d7f27637c48961Svet Ganov                CharSequence message = mAppLabel != null
1780cf1298a44d8fa062030e6e6e0d7f27637c48961Svet Ganov                        ? getString(R.string.bluetooth_ask_lasting_discovery, mAppLabel)
1790cf1298a44d8fa062030e6e6e0d7f27637c48961Svet Ganov                        : getString(R.string.bluetooth_ask_lasting_discovery_no_name);
1800cf1298a44d8fa062030e6e6e0d7f27637c48961Svet Ganov                builder.setMessage(message);
1811b0489cb3eb051b2cf18aa2cb3110ff904c9ebe8Chris Wren            } else {
1820cf1298a44d8fa062030e6e6e0d7f27637c48961Svet Ganov                CharSequence message = mAppLabel != null
183ebbfce0bf1cebf74525c9cceeeedcd1fe6012b60Jack He                        ? getString(R.string.bluetooth_ask_discovery, mAppLabel, mTimeout)
184ebbfce0bf1cebf74525c9cceeeedcd1fe6012b60Jack He                        : getString(R.string.bluetooth_ask_discovery_no_name, mTimeout);
1850cf1298a44d8fa062030e6e6e0d7f27637c48961Svet Ganov                builder.setMessage(message);
1861b0489cb3eb051b2cf18aa2cb3110ff904c9ebe8Chris Wren            }
18795c1003f1c6ea957065fa752d89c9f64b599461cJake Hamby            builder.setPositiveButton(getString(R.string.allow), this);
18895c1003f1c6ea957065fa752d89c9f64b599461cJake Hamby            builder.setNegativeButton(getString(R.string.deny), this);
189e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan        }
190e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan
191a0de1dcd1960181d9d8fd2e44f19dead16021e2bMichael Chan        mDialog = builder.create();
192a0de1dcd1960181d9d8fd2e44f19dead16021e2bMichael Chan        mDialog.show();
193e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan    }
194e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan
195e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan    @Override
196e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
197b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov        if (resultCode != Activity.RESULT_OK) {
198b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov            cancelAndFinish();
199a0de1dcd1960181d9d8fd2e44f19dead16021e2bMichael Chan            return;
200e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan        }
201e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan
202b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov        switch (mRequest) {
203b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov            case REQUEST_ENABLE:
204b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov            case REQUEST_ENABLE_DISCOVERABLE: {
205b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov                if (mLocalAdapter.getBluetoothState() == BluetoothAdapter.STATE_ON) {
206b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov                    proceedAndFinish();
207b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov                } else {
208b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov                    // If BT is not up yet, show "Turning on Bluetooth..."
209b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov                    mReceiver = new StateChangeReceiver();
210b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov                    registerReceiver(mReceiver, new IntentFilter(
211b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov                            BluetoothAdapter.ACTION_STATE_CHANGED));
212b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov                    createDialog();
213b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov                }
214b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov            } break;
215e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan
216b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov            case REQUEST_DISABLE: {
217b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov                if (mLocalAdapter.getBluetoothState() == BluetoothAdapter.STATE_OFF) {
218b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov                    proceedAndFinish();
219b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov                } else {
220b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov                    // If BT is not up yet, show "Turning off Bluetooth..."
221b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov                    mReceiver = new StateChangeReceiver();
222b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov                    registerReceiver(mReceiver, new IntentFilter(
223b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov                            BluetoothAdapter.ACTION_STATE_CHANGED));
224b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov                    createDialog();
225b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov                }
226b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov            } break;
227b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov
228b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov            default: {
229b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov                cancelAndFinish();
230b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov            } break;
231e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan        }
232e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan    }
233e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan
234e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan    public void onClick(DialogInterface dialog, int which) {
235e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan        switch (which) {
236e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan            case DialogInterface.BUTTON_POSITIVE:
237a0de1dcd1960181d9d8fd2e44f19dead16021e2bMichael Chan                proceedAndFinish();
238e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan                break;
239e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan
240e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan            case DialogInterface.BUTTON_NEGATIVE:
241436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby                setResult(RESULT_CANCELED);
242a0de1dcd1960181d9d8fd2e44f19dead16021e2bMichael Chan                finish();
243e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan                break;
244e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan        }
245e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan    }
246e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan
247a0de1dcd1960181d9d8fd2e44f19dead16021e2bMichael Chan    private void proceedAndFinish() {
248e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan        int returnCode;
249e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan
250b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov        if (mRequest == REQUEST_ENABLE || mRequest == REQUEST_DISABLE) {
251b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov            // BT toggled. Done
252436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby            returnCode = RESULT_OK;
25317d2124c1ccb1bd46393f70252d06d866646e97dWei Wang        } else if (mLocalAdapter.setScanMode(
254e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan                BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE, mTimeout)) {
255e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan            // If already in discoverable mode, this will extend the timeout.
2564bb010a67f80f5224b0777b48abdb08403b87616Srikanth Uppala            long endTime = System.currentTimeMillis() + (long) mTimeout * 1000;
257436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby            LocalBluetoothPreferences.persistDiscoverableEndTimestamp(
2584bb010a67f80f5224b0777b48abdb08403b87616Srikanth Uppala                    this, endTime);
2594bb010a67f80f5224b0777b48abdb08403b87616Srikanth Uppala            if (0 < mTimeout) {
2604bb010a67f80f5224b0777b48abdb08403b87616Srikanth Uppala               BluetoothDiscoverableTimeoutReceiver.setDiscoverableAlarm(this, endTime);
2614bb010a67f80f5224b0777b48abdb08403b87616Srikanth Uppala            }
262e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan            returnCode = mTimeout;
263834e5993e4f2f34d5aceb3196601b30231d00b07Michael Chan            // Activity.RESULT_FIRST_USER should be 1
264436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby            if (returnCode < RESULT_FIRST_USER) {
265436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby                returnCode = RESULT_FIRST_USER;
266834e5993e4f2f34d5aceb3196601b30231d00b07Michael Chan            }
267e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan        } else {
268436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby            returnCode = RESULT_CANCELED;
269e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan        }
270e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan
271a0de1dcd1960181d9d8fd2e44f19dead16021e2bMichael Chan        if (mDialog != null) {
272a0de1dcd1960181d9d8fd2e44f19dead16021e2bMichael Chan            mDialog.dismiss();
273e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan        }
274a0de1dcd1960181d9d8fd2e44f19dead16021e2bMichael Chan
275a0de1dcd1960181d9d8fd2e44f19dead16021e2bMichael Chan        setResult(returnCode);
276a0de1dcd1960181d9d8fd2e44f19dead16021e2bMichael Chan        finish();
277e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan    }
278e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan
279b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov    private void cancelAndFinish() {
280b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov        setResult(Activity.RESULT_CANCELED);
281b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov        finish();
282b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov    }
283b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov
284436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby    /**
285436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby     * Parse the received Intent and initialize mLocalBluetoothAdapter.
286436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby     * @return true if an error occurred; false otherwise
287436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby     */
288e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan    private boolean parseIntent() {
289e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan        Intent intent = getIntent();
290b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov        if (intent == null) {
291b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov            return true;
292b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov        }
293b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov        if (intent.getAction().equals(BluetoothAdapter.ACTION_REQUEST_ENABLE)) {
294b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov            mRequest = REQUEST_ENABLE;
295b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov        } else if (intent.getAction().equals(BluetoothAdapter.ACTION_REQUEST_DISABLE)) {
296b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov            mRequest = REQUEST_DISABLE;
297b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov        } else if (intent.getAction().equals(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE)) {
298b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov            mRequest = REQUEST_ENABLE_DISCOVERABLE;
299e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan            mTimeout = intent.getIntExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION,
300e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan                    BluetoothDiscoverableEnabler.DEFAULT_DISCOVERABLE_TIMEOUT);
301e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan
302d955af8461b845a1ce4f9beba9decfc2cffb0966Jaikumar Ganesh            Log.d(TAG, "Setting Bluetooth Discoverable Timeout = " + mTimeout);
303e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan
3046dcab67c0ccf5d9a644059260a16f46a07043eeeAjay Panicker            if (mTimeout < 1 || mTimeout > MAX_DISCOVERABLE_TIMEOUT) {
305e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan                mTimeout = BluetoothDiscoverableEnabler.DEFAULT_DISCOVERABLE_TIMEOUT;
306e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan            }
307e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan        } else {
308e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan            Log.e(TAG, "Error: this activity may be started only with intent "
309e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan                    + BluetoothAdapter.ACTION_REQUEST_ENABLE + " or "
310e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan                    + BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
311436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby            setResult(RESULT_CANCELED);
312e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan            return true;
313e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan        }
314e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan
315f2982a9ba19340b474bafb6b0bf5832673984e0dJason Monk        LocalBluetoothManager manager = Utils.getLocalBtManager(this);
316436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby        if (manager == null) {
317436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby            Log.e(TAG, "Error: there's a problem starting Bluetooth");
318436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby            setResult(RESULT_CANCELED);
319e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan            return true;
320e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan        }
3210cf1298a44d8fa062030e6e6e0d7f27637c48961Svet Ganov
3220cf1298a44d8fa062030e6e6e0d7f27637c48961Svet Ganov        String packageName = getCallingPackage();
3230cf1298a44d8fa062030e6e6e0d7f27637c48961Svet Ganov        if (TextUtils.isEmpty(packageName)) {
3240cf1298a44d8fa062030e6e6e0d7f27637c48961Svet Ganov            packageName = getIntent().getStringExtra(Intent.EXTRA_PACKAGE_NAME);
3250cf1298a44d8fa062030e6e6e0d7f27637c48961Svet Ganov        }
3260cf1298a44d8fa062030e6e6e0d7f27637c48961Svet Ganov        if (!TextUtils.isEmpty(packageName)) {
3270cf1298a44d8fa062030e6e6e0d7f27637c48961Svet Ganov            try {
3280cf1298a44d8fa062030e6e6e0d7f27637c48961Svet Ganov                ApplicationInfo applicationInfo = getPackageManager().getApplicationInfo(
3290cf1298a44d8fa062030e6e6e0d7f27637c48961Svet Ganov                        packageName, 0);
3300cf1298a44d8fa062030e6e6e0d7f27637c48961Svet Ganov                mAppLabel = applicationInfo.loadSafeLabel(getPackageManager());
3310cf1298a44d8fa062030e6e6e0d7f27637c48961Svet Ganov            } catch (PackageManager.NameNotFoundException e) {
3320cf1298a44d8fa062030e6e6e0d7f27637c48961Svet Ganov                Log.e(TAG, "Couldn't find app with package name " + packageName);
3330cf1298a44d8fa062030e6e6e0d7f27637c48961Svet Ganov                setResult(RESULT_CANCELED);
3340cf1298a44d8fa062030e6e6e0d7f27637c48961Svet Ganov                return true;
3350cf1298a44d8fa062030e6e6e0d7f27637c48961Svet Ganov            }
3360cf1298a44d8fa062030e6e6e0d7f27637c48961Svet Ganov        }
3370cf1298a44d8fa062030e6e6e0d7f27637c48961Svet Ganov
338436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby        mLocalAdapter = manager.getBluetoothAdapter();
339e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan
340e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan        return false;
341e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan    }
342e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan
343e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan    @Override
344e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan    protected void onDestroy() {
345e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan        super.onDestroy();
346b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov        if (mReceiver != null) {
347436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby            unregisterReceiver(mReceiver);
348b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov            mReceiver = null;
349436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby        }
350e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan    }
351e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan
352e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan    @Override
353e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan    public void onBackPressed() {
354436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby        setResult(RESULT_CANCELED);
355e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan        super.onBackPressed();
356e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan    }
357b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov
358b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov    private final class StateChangeReceiver extends BroadcastReceiver {
359b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov        private static final long TOGGLE_TIMEOUT_MILLIS = 10000; // 10 sec
360b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov
361b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov        public StateChangeReceiver() {
362b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov            getWindow().getDecorView().postDelayed(() -> {
363b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov                if (!isFinishing() && !isDestroyed()) {
364b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov                    cancelAndFinish();
365b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov                }
366b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov            }, TOGGLE_TIMEOUT_MILLIS);
367b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov        }
368b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov
369b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov        public void onReceive(Context context, Intent intent) {
370b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov            if (intent == null) {
371b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov                return;
372b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov            }
373b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov            final int currentState = intent.getIntExtra(
374b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov                    BluetoothAdapter.EXTRA_STATE, BluetoothDevice.ERROR);
375b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov            switch (mRequest) {
376b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov                case REQUEST_ENABLE:
377b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov                case REQUEST_ENABLE_DISCOVERABLE: {
378b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov                    if (currentState == BluetoothAdapter.STATE_ON) {
379b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov                        proceedAndFinish();
380b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov                    }
381b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov                } break;
382b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov
383b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov                case REQUEST_DISABLE: {
384b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov                    if (currentState == BluetoothAdapter.STATE_OFF) {
385b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov                        proceedAndFinish();
386b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov                    }
387b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov                } break;
388b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov            }
389b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov        }
390b06766f129dac138568883110f6d2a085b53445bSvetoslav Ganov    }
391e1089ad33896f4fe5b75e773813367d700773b6fMichael Chan}
392