CachedBluetoothDevice.java revision 39ef225e7c44a48aa9cfdf5c56ecd4ddfb95ae89
1afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project/*
2afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * Copyright (C) 2008 The Android Open Source Project
3afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project *
4afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
5afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * you may not use this file except in compliance with the License.
6afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * You may obtain a copy of the License at
7afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project *
8afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
9afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project *
10afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * Unless required by applicable law or agreed to in writing, software
11afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
12afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * See the License for the specific language governing permissions and
14afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * limitations under the License.
15afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project */
16afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
17afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectpackage com.android.settings.bluetooth;
18afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
1948e90002839e662eb1667471aebeb0483e9fb7dbAmith Yamasaniimport com.android.settings.R;
2048e90002839e662eb1667471aebeb0483e9fb7dbAmith Yamasani
2148e90002839e662eb1667471aebeb0483e9fb7dbAmith Yamasaniimport com.android.settings.SettingsPreferenceFragment;
2248e90002839e662eb1667471aebeb0483e9fb7dbAmith Yamasaniimport com.android.settings.bluetooth.LocalBluetoothProfileManager.Profile;
2348e90002839e662eb1667471aebeb0483e9fb7dbAmith Yamasani
24afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport android.app.AlertDialog;
25d63c0112251ab4e4e977545368dd703d875012a4Nick Pellyimport android.bluetooth.BluetoothAdapter;
262aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chanimport android.bluetooth.BluetoothClass;
27e6dd1fa1851302710ac7845d25d8ad8a5b6ee438The Android Open Source Projectimport android.bluetooth.BluetoothDevice;
28afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport android.content.Context;
29afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport android.content.DialogInterface;
30afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport android.content.res.Resources;
3148e90002839e662eb1667471aebeb0483e9fb7dbAmith Yamasaniimport android.graphics.drawable.Drawable;
32e6531e253bf646324d3a68de0e9cc612c5e1c8acMichael Chanimport android.os.ParcelUuid;
332aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chanimport android.os.SystemClock;
3448e90002839e662eb1667471aebeb0483e9fb7dbAmith Yamasaniimport android.preference.Preference;
3548e90002839e662eb1667471aebeb0483e9fb7dbAmith Yamasaniimport android.preference.PreferenceActivity;
36afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport android.text.TextUtils;
37afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport android.util.Log;
38afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
39afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport java.util.ArrayList;
40c090feb64f674d9840993736a24f9667f8b0e0d5Jake Hambyimport java.util.HashMap;
41afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport java.util.List;
42c090feb64f674d9840993736a24f9667f8b0e0d5Jake Hambyimport java.util.Map;
43afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
44afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project/**
45d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly * CachedBluetoothDevice represents a remote Bluetooth device. It contains
46afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * attributes of the device (such as the address, name, RSSI, etc.) and
47afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * functionality that can be performed on the device (connect, pair, disconnect,
48afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * etc.).
49afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project */
5039ef225e7c44a48aa9cfdf5c56ecd4ddfb95ae89Jake Hambyclass CachedBluetoothDevice implements Comparable<CachedBluetoothDevice> {
51d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly    private static final String TAG = "CachedBluetoothDevice";
52f25063aee3d8eeaf3767b3a4bf43e1895f2deb2dMichael Chan    private static final boolean D = LocalBluetoothManager.D;
53f25063aee3d8eeaf3767b3a4bf43e1895f2deb2dMichael Chan    private static final boolean V = LocalBluetoothManager.V;
54293867bd109383a1a26b35bf6accb92c0bad264cMichael Chan    private static final boolean DEBUG = false;
55afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
56d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly    private final BluetoothDevice mDevice;
57afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    private String mName;
58afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    private short mRssi;
5916cc86315d7a8e1f6a0f3083d0a810a7cb097832Nick Pelly    private BluetoothClass mBtClass;
6048e90002839e662eb1667471aebeb0483e9fb7dbAmith Yamasani    private Context mContext;
61afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
62afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    private List<Profile> mProfiles = new ArrayList<Profile>();
63afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
64afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    private boolean mVisible;
65afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
66afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    private final LocalBluetoothManager mLocalManager;
67afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
6820108e2ed6d7fdc889d85702f7cbda906db141cfJiehua.Dai    private AlertDialog mDialog = null;
6920108e2ed6d7fdc889d85702f7cbda906db141cfJiehua.Dai
70afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    private List<Callback> mCallbacks = new ArrayList<Callback>();
71afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
72afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    /**
73afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project     * When we connect to multiple profiles, we only want to display a single
74afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project     * error even if they all fail. This tracks that state.
75afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project     */
76afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    private boolean mIsConnectingErrorPossible;
77afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
782aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan    /**
79eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan     * Last time a bt profile auto-connect was attempted.
80eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan     * If an ACTION_UUID intent comes in within
812aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan     * MAX_UUID_DELAY_FOR_AUTO_CONNECT milliseconds, we will try auto-connect
822aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan     * again with the new UUIDs
832aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan     */
84eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan    private long mConnectAttempted;
852aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan
86eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan    // See mConnectAttempted
872aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan    private static final long MAX_UUID_DELAY_FOR_AUTO_CONNECT = 5000;
882aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan
89dd79a33ba53fec530094f4d2fe37f0538530d9f8Jake Hamby    /** Auto-connect after pairing only if locally initiated. */
90dd79a33ba53fec530094f4d2fe37f0538530d9f8Jake Hamby    private boolean mConnectAfterPairing;
9184905edb6315ac0af53141cf2f91591443d7422aJaikumar Ganesh
92e6dd1fa1851302710ac7845d25d8ad8a5b6ee438The Android Open Source Project    /**
93f907e0bb891eca4d498871a1cc862117a462a076Adam Powell     * Describes the current device and profile for logging.
9484905edb6315ac0af53141cf2f91591443d7422aJaikumar Ganesh     *
95f907e0bb891eca4d498871a1cc862117a462a076Adam Powell     * @param profile Profile to describe
96f907e0bb891eca4d498871a1cc862117a462a076Adam Powell     * @return Description of the device and profile
97e6dd1fa1851302710ac7845d25d8ad8a5b6ee438The Android Open Source Project     */
98e79f990490de49b39097433707c2bae6d8238330Jake Hamby    private String describe(Profile profile) {
99f907e0bb891eca4d498871a1cc862117a462a076Adam Powell        StringBuilder sb = new StringBuilder();
100e79f990490de49b39097433707c2bae6d8238330Jake Hamby        sb.append("Address:").append(mDevice);
101f907e0bb891eca4d498871a1cc862117a462a076Adam Powell        if (profile != null) {
102f907e0bb891eca4d498871a1cc862117a462a076Adam Powell            sb.append(" Profile:").append(profile.name());
103097ed6c671ed733c0967acc32e017020ede4575bMichael Chan        }
104e6dd1fa1851302710ac7845d25d8ad8a5b6ee438The Android Open Source Project
105f907e0bb891eca4d498871a1cc862117a462a076Adam Powell        return sb.toString();
106f907e0bb891eca4d498871a1cc862117a462a076Adam Powell    }
10784905edb6315ac0af53141cf2f91591443d7422aJaikumar Ganesh
1086c97742c88303c65e68fe08257a7ccf841f03866Michael Chan    public void onProfileStateChanged(Profile profile, int newProfileState) {
109f907e0bb891eca4d498871a1cc862117a462a076Adam Powell        if (D) {
110f907e0bb891eca4d498871a1cc862117a462a076Adam Powell            Log.d(TAG, "onProfileStateChanged: profile " + profile.toString() +
111f907e0bb891eca4d498871a1cc862117a462a076Adam Powell                    " newProfileState " + newProfileState);
1126c97742c88303c65e68fe08257a7ccf841f03866Michael Chan        }
113e6dd1fa1851302710ac7845d25d8ad8a5b6ee438The Android Open Source Project
114f907e0bb891eca4d498871a1cc862117a462a076Adam Powell        int newState = LocalBluetoothProfileManager.getProfileManager(mLocalManager,
115f907e0bb891eca4d498871a1cc862117a462a076Adam Powell                profile).convertState(newProfileState);
116f907e0bb891eca4d498871a1cc862117a462a076Adam Powell
117f907e0bb891eca4d498871a1cc862117a462a076Adam Powell        if (newState == SettingsBtStatus.CONNECTION_STATUS_CONNECTED) {
118f907e0bb891eca4d498871a1cc862117a462a076Adam Powell            if (!mProfiles.contains(profile)) {
119f907e0bb891eca4d498871a1cc862117a462a076Adam Powell                mProfiles.add(profile);
120e6dd1fa1851302710ac7845d25d8ad8a5b6ee438The Android Open Source Project            }
121e6dd1fa1851302710ac7845d25d8ad8a5b6ee438The Android Open Source Project        }
122e6dd1fa1851302710ac7845d25d8ad8a5b6ee438The Android Open Source Project    }
123e6dd1fa1851302710ac7845d25d8ad8a5b6ee438The Android Open Source Project
124d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly    CachedBluetoothDevice(Context context, BluetoothDevice device) {
125afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        mLocalManager = LocalBluetoothManager.getInstance(context);
126afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        if (mLocalManager == null) {
127afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            throw new IllegalStateException(
128d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly                    "Cannot use CachedBluetoothDevice without Bluetooth hardware");
129afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        }
130afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
131d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly        mDevice = device;
13248e90002839e662eb1667471aebeb0483e9fb7dbAmith Yamasani        mContext = context;
133afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
134afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        fillData();
135afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    }
136afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
137afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    public void onClicked() {
138afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        int bondState = getBondState();
139afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
140afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        if (isConnected()) {
141afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            askDisconnect();
142afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        } else if (bondState == BluetoothDevice.BOND_BONDED) {
143afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            connect();
14416cc86315d7a8e1f6a0f3083d0a810a7cb097832Nick Pelly        } else if (bondState == BluetoothDevice.BOND_NONE) {
145afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            pair();
146afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        }
147afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    }
148afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
149afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    public void disconnect() {
150afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        for (Profile profile : mProfiles) {
151afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            disconnect(profile);
152afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        }
153afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    }
154afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
155afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    public void disconnect(Profile profile) {
156afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        LocalBluetoothProfileManager profileManager =
157afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                LocalBluetoothProfileManager.getProfileManager(mLocalManager, profile);
158e79f990490de49b39097433707c2bae6d8238330Jake Hamby        if (profileManager.disconnect(mDevice)) {
159d3a460cce7b6a4f1e81f3c15b5f7949d28fdc929Jaikumar Ganesh            if (D) {
160d3a460cce7b6a4f1e81f3c15b5f7949d28fdc929Jaikumar Ganesh                Log.d(TAG, "Command sent successfully:DISCONNECT " + describe(profile));
161f907e0bb891eca4d498871a1cc862117a462a076Adam Powell            }
162afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        }
163afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    }
164afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
165afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    public void askDisconnect() {
166afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        Context context = mLocalManager.getForegroundActivity();
167afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        if (context == null) {
168afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            // Cannot ask, since we need an activity context
169afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            disconnect();
170afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            return;
171afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        }
172afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
173afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        Resources res = context.getResources();
174afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
175afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        String name = getName();
176afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        if (TextUtils.isEmpty(name)) {
177afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            name = res.getString(R.string.bluetooth_device);
178afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        }
179afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        String message = res.getString(R.string.bluetooth_disconnect_blank, name);
180afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
181afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        DialogInterface.OnClickListener disconnectListener = new DialogInterface.OnClickListener() {
182afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            public void onClick(DialogInterface dialog, int which) {
183afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                disconnect();
184afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            }
185afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        };
186afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
187e79f990490de49b39097433707c2bae6d8238330Jake Hamby        showDisconnectDialog(context, disconnectListener, message);
188e79f990490de49b39097433707c2bae6d8238330Jake Hamby    }
189e79f990490de49b39097433707c2bae6d8238330Jake Hamby
190e79f990490de49b39097433707c2bae6d8238330Jake Hamby    public void askDisconnect(final Profile profile) {
191e79f990490de49b39097433707c2bae6d8238330Jake Hamby        Context context = mLocalManager.getForegroundActivity();
192e79f990490de49b39097433707c2bae6d8238330Jake Hamby        if (context == null) {
193e79f990490de49b39097433707c2bae6d8238330Jake Hamby            // Cannot ask, since we need an activity context
194e79f990490de49b39097433707c2bae6d8238330Jake Hamby            disconnect(profile);
195e79f990490de49b39097433707c2bae6d8238330Jake Hamby            return;
196e79f990490de49b39097433707c2bae6d8238330Jake Hamby        }
197e79f990490de49b39097433707c2bae6d8238330Jake Hamby
198e79f990490de49b39097433707c2bae6d8238330Jake Hamby        Resources res = context.getResources();
199e79f990490de49b39097433707c2bae6d8238330Jake Hamby
200e79f990490de49b39097433707c2bae6d8238330Jake Hamby        String name = getName();
201e79f990490de49b39097433707c2bae6d8238330Jake Hamby        if (TextUtils.isEmpty(name)) {
202e79f990490de49b39097433707c2bae6d8238330Jake Hamby            name = res.getString(R.string.bluetooth_device);
203e79f990490de49b39097433707c2bae6d8238330Jake Hamby        }
204e79f990490de49b39097433707c2bae6d8238330Jake Hamby        int disconnectMessage;
205e79f990490de49b39097433707c2bae6d8238330Jake Hamby        switch (profile) {
206e79f990490de49b39097433707c2bae6d8238330Jake Hamby            case A2DP:
207e79f990490de49b39097433707c2bae6d8238330Jake Hamby                disconnectMessage = R.string.bluetooth_disconnect_a2dp_profile;
208e79f990490de49b39097433707c2bae6d8238330Jake Hamby                break;
209e79f990490de49b39097433707c2bae6d8238330Jake Hamby            case HEADSET:
210e79f990490de49b39097433707c2bae6d8238330Jake Hamby                disconnectMessage = R.string.bluetooth_disconnect_headset_profile;
211e79f990490de49b39097433707c2bae6d8238330Jake Hamby                break;
212e79f990490de49b39097433707c2bae6d8238330Jake Hamby            case HID:
213e79f990490de49b39097433707c2bae6d8238330Jake Hamby                disconnectMessage = R.string.bluetooth_disconnect_hid_profile;
214e79f990490de49b39097433707c2bae6d8238330Jake Hamby                break;
215e79f990490de49b39097433707c2bae6d8238330Jake Hamby            case PAN:
216e79f990490de49b39097433707c2bae6d8238330Jake Hamby                disconnectMessage = R.string.bluetooth_disconnect_pan_profile;
217e79f990490de49b39097433707c2bae6d8238330Jake Hamby                break;
218e79f990490de49b39097433707c2bae6d8238330Jake Hamby            default:
219e79f990490de49b39097433707c2bae6d8238330Jake Hamby                Log.w(TAG, "askDisconnect: unexpected profile " + profile);
220e79f990490de49b39097433707c2bae6d8238330Jake Hamby                disconnectMessage = R.string.bluetooth_disconnect_blank;
221e79f990490de49b39097433707c2bae6d8238330Jake Hamby                break;
222e79f990490de49b39097433707c2bae6d8238330Jake Hamby        }
223e79f990490de49b39097433707c2bae6d8238330Jake Hamby        String message = res.getString(disconnectMessage, name);
224e79f990490de49b39097433707c2bae6d8238330Jake Hamby
225e79f990490de49b39097433707c2bae6d8238330Jake Hamby        DialogInterface.OnClickListener disconnectListener =
226e79f990490de49b39097433707c2bae6d8238330Jake Hamby                new DialogInterface.OnClickListener() {
227e79f990490de49b39097433707c2bae6d8238330Jake Hamby            public void onClick(DialogInterface dialog, int which) {
228e79f990490de49b39097433707c2bae6d8238330Jake Hamby                disconnect(profile);
229e79f990490de49b39097433707c2bae6d8238330Jake Hamby            }
230e79f990490de49b39097433707c2bae6d8238330Jake Hamby        };
231e79f990490de49b39097433707c2bae6d8238330Jake Hamby
232e79f990490de49b39097433707c2bae6d8238330Jake Hamby        showDisconnectDialog(context, disconnectListener, message);
233e79f990490de49b39097433707c2bae6d8238330Jake Hamby    }
234e79f990490de49b39097433707c2bae6d8238330Jake Hamby
235e79f990490de49b39097433707c2bae6d8238330Jake Hamby    private void showDisconnectDialog(Context context,
236e79f990490de49b39097433707c2bae6d8238330Jake Hamby            DialogInterface.OnClickListener disconnectListener,
237e79f990490de49b39097433707c2bae6d8238330Jake Hamby            String message) {
23820108e2ed6d7fdc889d85702f7cbda906db141cfJiehua.Dai        if (mDialog == null) {
23920108e2ed6d7fdc889d85702f7cbda906db141cfJiehua.Dai            mDialog = new AlertDialog.Builder(context)
24020108e2ed6d7fdc889d85702f7cbda906db141cfJiehua.Dai                    .setPositiveButton(android.R.string.ok, disconnectListener)
24120108e2ed6d7fdc889d85702f7cbda906db141cfJiehua.Dai                    .setNegativeButton(android.R.string.cancel, null)
24220108e2ed6d7fdc889d85702f7cbda906db141cfJiehua.Dai                    .create();
24320108e2ed6d7fdc889d85702f7cbda906db141cfJiehua.Dai        } else {
24420108e2ed6d7fdc889d85702f7cbda906db141cfJiehua.Dai            if (mDialog.isShowing()) {
24520108e2ed6d7fdc889d85702f7cbda906db141cfJiehua.Dai                mDialog.dismiss();
24620108e2ed6d7fdc889d85702f7cbda906db141cfJiehua.Dai            }
247e79f990490de49b39097433707c2bae6d8238330Jake Hamby            // use disconnectListener for the correct profile(s)
248e79f990490de49b39097433707c2bae6d8238330Jake Hamby            CharSequence okText = context.getText(android.R.string.ok);
249e79f990490de49b39097433707c2bae6d8238330Jake Hamby            mDialog.setButton(DialogInterface.BUTTON_POSITIVE,
250e79f990490de49b39097433707c2bae6d8238330Jake Hamby                    okText, disconnectListener);
25120108e2ed6d7fdc889d85702f7cbda906db141cfJiehua.Dai        }
25220108e2ed6d7fdc889d85702f7cbda906db141cfJiehua.Dai        mDialog.setTitle(getName());
25320108e2ed6d7fdc889d85702f7cbda906db141cfJiehua.Dai        mDialog.setMessage(message);
25420108e2ed6d7fdc889d85702f7cbda906db141cfJiehua.Dai        mDialog.show();
25520108e2ed6d7fdc889d85702f7cbda906db141cfJiehua.Dai    }
25620108e2ed6d7fdc889d85702f7cbda906db141cfJiehua.Dai
25720108e2ed6d7fdc889d85702f7cbda906db141cfJiehua.Dai    @Override
25820108e2ed6d7fdc889d85702f7cbda906db141cfJiehua.Dai    protected void finalize() throws Throwable {
25920108e2ed6d7fdc889d85702f7cbda906db141cfJiehua.Dai        if (mDialog != null) {
26020108e2ed6d7fdc889d85702f7cbda906db141cfJiehua.Dai            mDialog.dismiss();
26120108e2ed6d7fdc889d85702f7cbda906db141cfJiehua.Dai            mDialog = null;
26220108e2ed6d7fdc889d85702f7cbda906db141cfJiehua.Dai        }
26320108e2ed6d7fdc889d85702f7cbda906db141cfJiehua.Dai
26420108e2ed6d7fdc889d85702f7cbda906db141cfJiehua.Dai        super.finalize();
265afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    }
266afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
267afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    public void connect() {
268afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        if (!ensurePaired()) return;
269afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
270eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan        mConnectAttempted = SystemClock.elapsedRealtime();
271eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan
27239ef225e7c44a48aa9cfdf5c56ecd4ddfb95ae89Jake Hamby        connectWithoutResettingTimer(true);
273eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan    }
274eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan
275b172cd5d232bd650d6efbb7d8b5e4cf9c213952fJaikumar Ganesh    /*package*/ void onBondingDockConnect() {
276582f1f84bb0ad4315ce17826672298c68f1c3b38Jake Hamby        // Attempt to connect if UUIDs are available. Otherwise,
277582f1f84bb0ad4315ce17826672298c68f1c3b38Jake Hamby        // we will connect when the ACTION_UUID intent arrives.
278582f1f84bb0ad4315ce17826672298c68f1c3b38Jake Hamby        connect();
279b172cd5d232bd650d6efbb7d8b5e4cf9c213952fJaikumar Ganesh    }
280b172cd5d232bd650d6efbb7d8b5e4cf9c213952fJaikumar Ganesh
28139ef225e7c44a48aa9cfdf5c56ecd4ddfb95ae89Jake Hamby    private void connectWithoutResettingTimer(boolean connectAllProfiles) {
2822aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan        // Try to initialize the profiles if there were not.
2832aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan        if (mProfiles.size() == 0) {
2842aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan            if (!updateProfiles()) {
2852aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan                // If UUIDs are not available yet, connect will be happen
2862aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan                // upon arrival of the ACTION_UUID intent.
287eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan                if (DEBUG) Log.d(TAG, "No profiles. Maybe we will connect later");
2882aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan                return;
2892aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan            }
2902aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan        }
2912aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan
292afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        // Reset the only-show-one-error-dialog tracking variable
293afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        mIsConnectingErrorPossible = true;
294afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
295eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan        int preferredProfiles = 0;
296afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        for (Profile profile : mProfiles) {
29739ef225e7c44a48aa9cfdf5c56ecd4ddfb95ae89Jake Hamby            if (connectAllProfiles ? profile.isConnectable() : profile.isAutoConnectable()) {
298b547dda338f1b135076c8be59c50a12d843cebf8Michael Chan                LocalBluetoothProfileManager profileManager = LocalBluetoothProfileManager
299b547dda338f1b135076c8be59c50a12d843cebf8Michael Chan                        .getProfileManager(mLocalManager, profile);
300b547dda338f1b135076c8be59c50a12d843cebf8Michael Chan                if (profileManager.isPreferred(mDevice)) {
301b547dda338f1b135076c8be59c50a12d843cebf8Michael Chan                    ++preferredProfiles;
30284905edb6315ac0af53141cf2f91591443d7422aJaikumar Ganesh                    disconnectConnected(this, profile);
303f907e0bb891eca4d498871a1cc862117a462a076Adam Powell                    connectInt(this, profile);
304b547dda338f1b135076c8be59c50a12d843cebf8Michael Chan                }
305afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            }
306afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        }
307eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan        if (DEBUG) Log.d(TAG, "Preferred profiles = " + preferredProfiles);
308afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
309eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan        if (preferredProfiles == 0) {
31039ef225e7c44a48aa9cfdf5c56ecd4ddfb95ae89Jake Hamby            connectAllAutoConnectableProfiles();
311afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        }
312afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    }
313afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
31439ef225e7c44a48aa9cfdf5c56ecd4ddfb95ae89Jake Hamby    private void connectAllAutoConnectableProfiles() {
315afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        if (!ensurePaired()) return;
316afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
317afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        // Reset the only-show-one-error-dialog tracking variable
318afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        mIsConnectingErrorPossible = true;
319afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
320afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        for (Profile profile : mProfiles) {
32139ef225e7c44a48aa9cfdf5c56ecd4ddfb95ae89Jake Hamby            if (profile.isAutoConnectable()) {
322b547dda338f1b135076c8be59c50a12d843cebf8Michael Chan                LocalBluetoothProfileManager profileManager = LocalBluetoothProfileManager
323b547dda338f1b135076c8be59c50a12d843cebf8Michael Chan                        .getProfileManager(mLocalManager, profile);
324c090feb64f674d9840993736a24f9667f8b0e0d5Jake Hamby                profileManager.setPreferred(mDevice, true);
32584905edb6315ac0af53141cf2f91591443d7422aJaikumar Ganesh                disconnectConnected(this, profile);
326f907e0bb891eca4d498871a1cc862117a462a076Adam Powell                connectInt(this, profile);
327b547dda338f1b135076c8be59c50a12d843cebf8Michael Chan            }
328afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        }
329afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    }
330afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
331afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    public void connect(Profile profile) {
332eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan        mConnectAttempted = SystemClock.elapsedRealtime();
333afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        // Reset the only-show-one-error-dialog tracking variable
334afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        mIsConnectingErrorPossible = true;
33584905edb6315ac0af53141cf2f91591443d7422aJaikumar Ganesh        disconnectConnected(this, profile);
336f907e0bb891eca4d498871a1cc862117a462a076Adam Powell        connectInt(this, profile);
337afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    }
338afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
33984905edb6315ac0af53141cf2f91591443d7422aJaikumar Ganesh    private void disconnectConnected(CachedBluetoothDevice device, Profile profile) {
3403327f7887328c55ef2d837a8e2a07cea2070c744Michael Chan        LocalBluetoothProfileManager profileManager =
3413327f7887328c55ef2d837a8e2a07cea2070c744Michael Chan            LocalBluetoothProfileManager.getProfileManager(mLocalManager, profile);
3423327f7887328c55ef2d837a8e2a07cea2070c744Michael Chan        CachedBluetoothDeviceManager cachedDeviceManager = mLocalManager.getCachedDeviceManager();
343659b39abf8580a49bd77f194c9ac30359f610709Jaikumar Ganesh        List<BluetoothDevice> devices = profileManager.getConnectedDevices();
3443327f7887328c55ef2d837a8e2a07cea2070c744Michael Chan        if (devices == null) return;
34584905edb6315ac0af53141cf2f91591443d7422aJaikumar Ganesh        for (BluetoothDevice btDevice : devices) {
34684905edb6315ac0af53141cf2f91591443d7422aJaikumar Ganesh            CachedBluetoothDevice cachedDevice = cachedDeviceManager.findDevice(btDevice);
34784905edb6315ac0af53141cf2f91591443d7422aJaikumar Ganesh
34884905edb6315ac0af53141cf2f91591443d7422aJaikumar Ganesh            if (cachedDevice != null && !cachedDevice.equals(device)) {
349e79f990490de49b39097433707c2bae6d8238330Jake Hamby                cachedDevice.disconnect(profile);
3503327f7887328c55ef2d837a8e2a07cea2070c744Michael Chan            }
3513327f7887328c55ef2d837a8e2a07cea2070c744Michael Chan        }
3523327f7887328c55ef2d837a8e2a07cea2070c744Michael Chan    }
3533327f7887328c55ef2d837a8e2a07cea2070c744Michael Chan
354d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly    private boolean connectInt(CachedBluetoothDevice cachedDevice, Profile profile) {
355d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly        if (!cachedDevice.ensurePaired()) return false;
356afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
357afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        LocalBluetoothProfileManager profileManager =
358afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                LocalBluetoothProfileManager.getProfileManager(mLocalManager, profile);
359e79f990490de49b39097433707c2bae6d8238330Jake Hamby
360d3a460cce7b6a4f1e81f3c15b5f7949d28fdc929Jaikumar Ganesh        if (profileManager.connect(cachedDevice.mDevice)) {
361d3a460cce7b6a4f1e81f3c15b5f7949d28fdc929Jaikumar Ganesh            if (D) {
362d3a460cce7b6a4f1e81f3c15b5f7949d28fdc929Jaikumar Ganesh                Log.d(TAG, "Command sent successfully:CONNECT " + describe(profile));
363afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            }
364d3a460cce7b6a4f1e81f3c15b5f7949d28fdc929Jaikumar Ganesh            return true;
365afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        }
366d3a460cce7b6a4f1e81f3c15b5f7949d28fdc929Jaikumar Ganesh        Log.i(TAG, "Failed to connect " + profile.toString() + " to " + cachedDevice.mName);
367f907e0bb891eca4d498871a1cc862117a462a076Adam Powell
368e6dd1fa1851302710ac7845d25d8ad8a5b6ee438The Android Open Source Project        return false;
369afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    }
370afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
371afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    public void showConnectingError() {
372afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        if (!mIsConnectingErrorPossible) return;
373afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        mIsConnectingErrorPossible = false;
374afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
37539ef225e7c44a48aa9cfdf5c56ecd4ddfb95ae89Jake Hamby        mLocalManager.showError(mDevice,
376afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                R.string.bluetooth_connecting_error_message);
377afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    }
378afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
379afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    private boolean ensurePaired() {
38016cc86315d7a8e1f6a0f3083d0a810a7cb097832Nick Pelly        if (getBondState() == BluetoothDevice.BOND_NONE) {
381afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            pair();
382afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            return false;
383afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        } else {
384afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            return true;
385afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        }
386afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    }
387afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
388afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    public void pair() {
389d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly        BluetoothAdapter adapter = mLocalManager.getBluetoothAdapter();
390afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
391afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        // Pairing is unreliable while scanning, so cancel discovery
392d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly        if (adapter.isDiscovering()) {
393d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly            adapter.cancelDiscovery();
394afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        }
395afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
396d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly        if (!mDevice.createBond()) {
39739ef225e7c44a48aa9cfdf5c56ecd4ddfb95ae89Jake Hamby            mLocalManager.showError(mDevice,
398afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                    R.string.bluetooth_pairing_error_message);
399dd79a33ba53fec530094f4d2fe37f0538530d9f8Jake Hamby            return;
400afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        }
401dd79a33ba53fec530094f4d2fe37f0538530d9f8Jake Hamby
402dd79a33ba53fec530094f4d2fe37f0538530d9f8Jake Hamby        mConnectAfterPairing = true;  // auto-connect after pairing
403afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    }
404afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
405afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    public void unpair() {
40696b0c1dc0813f7e8c957ec17dc7751693926c6aeMichael Chan        disconnect();
407e6dd1fa1851302710ac7845d25d8ad8a5b6ee438The Android Open Source Project
40896b0c1dc0813f7e8c957ec17dc7751693926c6aeMichael Chan        int state = getBondState();
409afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
41096b0c1dc0813f7e8c957ec17dc7751693926c6aeMichael Chan        if (state == BluetoothDevice.BOND_BONDING) {
411d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly            mDevice.cancelBondProcess();
41296b0c1dc0813f7e8c957ec17dc7751693926c6aeMichael Chan        }
41396b0c1dc0813f7e8c957ec17dc7751693926c6aeMichael Chan
41496b0c1dc0813f7e8c957ec17dc7751693926c6aeMichael Chan        if (state != BluetoothDevice.BOND_NONE) {
415f907e0bb891eca4d498871a1cc862117a462a076Adam Powell            final BluetoothDevice dev = getDevice();
416f907e0bb891eca4d498871a1cc862117a462a076Adam Powell            if (dev != null) {
417f907e0bb891eca4d498871a1cc862117a462a076Adam Powell                final boolean successful = dev.removeBond();
418f907e0bb891eca4d498871a1cc862117a462a076Adam Powell                if (successful) {
419f907e0bb891eca4d498871a1cc862117a462a076Adam Powell                    if (D) {
420f907e0bb891eca4d498871a1cc862117a462a076Adam Powell                        Log.d(TAG, "Command sent successfully:REMOVE_BOND " + describe(null));
421f907e0bb891eca4d498871a1cc862117a462a076Adam Powell                    }
422f907e0bb891eca4d498871a1cc862117a462a076Adam Powell                } else if (V) {
423f907e0bb891eca4d498871a1cc862117a462a076Adam Powell                    Log.v(TAG, "Framework rejected command immediately:REMOVE_BOND " +
424f907e0bb891eca4d498871a1cc862117a462a076Adam Powell                            describe(null));
425f907e0bb891eca4d498871a1cc862117a462a076Adam Powell                }
426f907e0bb891eca4d498871a1cc862117a462a076Adam Powell            }
427afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        }
428afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    }
429afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
430afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    private void fillData() {
431afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        fetchName();
432afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        fetchBtClass();
4332aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan        updateProfiles();
434afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
435afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        mVisible = false;
436afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
437afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        dispatchAttributesChanged();
438afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    }
439afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
440d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly    public BluetoothDevice getDevice() {
441d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly        return mDevice;
442afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    }
443afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
444afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    public String getName() {
445afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        return mName;
446afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    }
447afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
448d97daa064b35ee0c2b73547d46f97fa88d2da4e9Jaikumar Ganesh    public void setName(String name) {
449d97daa064b35ee0c2b73547d46f97fa88d2da4e9Jaikumar Ganesh        if (!mName.equals(name)) {
450d97daa064b35ee0c2b73547d46f97fa88d2da4e9Jaikumar Ganesh            if (TextUtils.isEmpty(name)) {
451c090feb64f674d9840993736a24f9667f8b0e0d5Jake Hamby                // TODO: use friendly name for unknown device (bug 1181856)
452d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly                mName = mDevice.getAddress();
453d97daa064b35ee0c2b73547d46f97fa88d2da4e9Jaikumar Ganesh            } else {
454d97daa064b35ee0c2b73547d46f97fa88d2da4e9Jaikumar Ganesh                mName = name;
455d97daa064b35ee0c2b73547d46f97fa88d2da4e9Jaikumar Ganesh            }
456c090feb64f674d9840993736a24f9667f8b0e0d5Jake Hamby            // TODO: save custom device name in preferences
457d97daa064b35ee0c2b73547d46f97fa88d2da4e9Jaikumar Ganesh            dispatchAttributesChanged();
458d97daa064b35ee0c2b73547d46f97fa88d2da4e9Jaikumar Ganesh        }
459d97daa064b35ee0c2b73547d46f97fa88d2da4e9Jaikumar Ganesh    }
460d97daa064b35ee0c2b73547d46f97fa88d2da4e9Jaikumar Ganesh
461afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    public void refreshName() {
462afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        fetchName();
463afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        dispatchAttributesChanged();
464afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    }
465afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
466afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    private void fetchName() {
467d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly        mName = mDevice.getName();
468afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
469afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        if (TextUtils.isEmpty(mName)) {
470d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly            mName = mDevice.getAddress();
471eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan            if (DEBUG) Log.d(TAG, "Default to address. Device has no name (yet) " + mName);
472afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        }
473afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    }
474afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
475afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    public void refresh() {
476afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        dispatchAttributesChanged();
477afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    }
478afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
479afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    public boolean isVisible() {
480afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        return mVisible;
481afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    }
482afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
483afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    void setVisible(boolean visible) {
484afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        if (mVisible != visible) {
485afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            mVisible = visible;
486afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            dispatchAttributesChanged();
487afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        }
488afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    }
489afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
490afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    public int getBondState() {
491d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly        return mDevice.getBondState();
492afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    }
493afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
494afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    void setRssi(short rssi) {
495afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        if (mRssi != rssi) {
496afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            mRssi = rssi;
497afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            dispatchAttributesChanged();
498afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        }
499afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    }
500afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
501afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    /**
502afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project     * Checks whether we are connected to this device (any profile counts).
503afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project     *
504afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project     * @return Whether it is connected.
505afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project     */
506afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    public boolean isConnected() {
507afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        for (Profile profile : mProfiles) {
508afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            int status = LocalBluetoothProfileManager.getProfileManager(mLocalManager, profile)
509d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly                    .getConnectionStatus(mDevice);
510afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            if (SettingsBtStatus.isConnectionStatusConnected(status)) {
511afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                return true;
512afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            }
513afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        }
514afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
515afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        return false;
516afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    }
517afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
518c090feb64f674d9840993736a24f9667f8b0e0d5Jake Hamby    public boolean isConnectedProfile(Profile profile) {
519c090feb64f674d9840993736a24f9667f8b0e0d5Jake Hamby        int status = LocalBluetoothProfileManager.getProfileManager(mLocalManager, profile)
520c090feb64f674d9840993736a24f9667f8b0e0d5Jake Hamby                .getConnectionStatus(mDevice);
521c090feb64f674d9840993736a24f9667f8b0e0d5Jake Hamby        if (SettingsBtStatus.isConnectionStatusConnected(status)) {
522c090feb64f674d9840993736a24f9667f8b0e0d5Jake Hamby            return true;
523c090feb64f674d9840993736a24f9667f8b0e0d5Jake Hamby        }
524c090feb64f674d9840993736a24f9667f8b0e0d5Jake Hamby
525c090feb64f674d9840993736a24f9667f8b0e0d5Jake Hamby        return false;
526c090feb64f674d9840993736a24f9667f8b0e0d5Jake Hamby    }
527c090feb64f674d9840993736a24f9667f8b0e0d5Jake Hamby
528afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    public boolean isBusy() {
529afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        for (Profile profile : mProfiles) {
530afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            int status = LocalBluetoothProfileManager.getProfileManager(mLocalManager, profile)
531d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly                    .getConnectionStatus(mDevice);
532afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            if (SettingsBtStatus.isConnectionStatusBusy(status)) {
533afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                return true;
534afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            }
535afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        }
536afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
537afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        if (getBondState() == BluetoothDevice.BOND_BONDING) {
538afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            return true;
539afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        }
540afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
541afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        return false;
542afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    }
543afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
544afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    public int getBtClassDrawable() {
5454d004e910732565ddd449c7c525f7d6cbd353392Michael Chan        if (mBtClass != null) {
5464d004e910732565ddd449c7c525f7d6cbd353392Michael Chan            switch (mBtClass.getMajorDeviceClass()) {
5474d004e910732565ddd449c7c525f7d6cbd353392Michael Chan            case BluetoothClass.Device.Major.COMPUTER:
5484d004e910732565ddd449c7c525f7d6cbd353392Michael Chan                return R.drawable.ic_bt_laptop;
549afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
5504d004e910732565ddd449c7c525f7d6cbd353392Michael Chan            case BluetoothClass.Device.Major.PHONE:
5514d004e910732565ddd449c7c525f7d6cbd353392Michael Chan                return R.drawable.ic_bt_cellphone;
5524d004e910732565ddd449c7c525f7d6cbd353392Michael Chan            }
5534d004e910732565ddd449c7c525f7d6cbd353392Michael Chan        } else {
5544d004e910732565ddd449c7c525f7d6cbd353392Michael Chan            Log.w(TAG, "mBtClass is null");
5553e1c1d19201e625888cdd07e06ea9502d7c4dafbMichael Chan        }
556afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
557cb844e2eab4efa03513c0e0a2de7bc18c79dd128Michael Chan        if (mProfiles.size() > 0) {
558cb844e2eab4efa03513c0e0a2de7bc18c79dd128Michael Chan            if (mProfiles.contains(Profile.A2DP)) {
559cb844e2eab4efa03513c0e0a2de7bc18c79dd128Michael Chan                return R.drawable.ic_bt_headphones_a2dp;
560cb844e2eab4efa03513c0e0a2de7bc18c79dd128Michael Chan            } else if (mProfiles.contains(Profile.HEADSET)) {
561cb844e2eab4efa03513c0e0a2de7bc18c79dd128Michael Chan                return R.drawable.ic_bt_headset_hfp;
562cb844e2eab4efa03513c0e0a2de7bc18c79dd128Michael Chan            }
5634d004e910732565ddd449c7c525f7d6cbd353392Michael Chan        } else if (mBtClass != null) {
564cb844e2eab4efa03513c0e0a2de7bc18c79dd128Michael Chan            if (mBtClass.doesClassMatch(BluetoothClass.PROFILE_A2DP)) {
565cb844e2eab4efa03513c0e0a2de7bc18c79dd128Michael Chan                return R.drawable.ic_bt_headphones_a2dp;
566cb844e2eab4efa03513c0e0a2de7bc18c79dd128Michael Chan
567cb844e2eab4efa03513c0e0a2de7bc18c79dd128Michael Chan            }
568cb844e2eab4efa03513c0e0a2de7bc18c79dd128Michael Chan            if (mBtClass.doesClassMatch(BluetoothClass.PROFILE_HEADSET)) {
569cb844e2eab4efa03513c0e0a2de7bc18c79dd128Michael Chan                return R.drawable.ic_bt_headset_hfp;
570cb844e2eab4efa03513c0e0a2de7bc18c79dd128Michael Chan            }
571afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        }
572cb844e2eab4efa03513c0e0a2de7bc18c79dd128Michael Chan        return 0;
573afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    }
574afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
575afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    /**
576afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project     * Fetches a new value for the cached BT class.
577afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project     */
578afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    private void fetchBtClass() {
579d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly        mBtClass = mDevice.getBluetoothClass();
5802aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan    }
5812aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan
5822aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan    private boolean updateProfiles() {
5832aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan        ParcelUuid[] uuids = mDevice.getUuids();
5842aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan        if (uuids == null) return false;
5852aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan
586498d12bac0df509a4f74a4df8a8c69ec22583a1aJaikumar Ganesh        BluetoothAdapter adapter = mLocalManager.getBluetoothAdapter();
587498d12bac0df509a4f74a4df8a8c69ec22583a1aJaikumar Ganesh        ParcelUuid[] localUuids = adapter.getUuids();
588498d12bac0df509a4f74a4df8a8c69ec22583a1aJaikumar Ganesh        if (localUuids == null) return false;
589498d12bac0df509a4f74a4df8a8c69ec22583a1aJaikumar Ganesh
590498d12bac0df509a4f74a4df8a8c69ec22583a1aJaikumar Ganesh        LocalBluetoothProfileManager.updateProfiles(uuids, localUuids, mProfiles);
5912aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan
5922aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan        if (DEBUG) {
5932aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan            Log.e(TAG, "updating profiles for " + mDevice.getName());
5942aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan            BluetoothClass bluetoothClass = mDevice.getBluetoothClass();
5952aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan
5968c04b90cc95b16f8d7e99a61d8e2c940ed83b0c4Jaikumar Ganesh            if (bluetoothClass != null) Log.v(TAG, "Class: " + bluetoothClass.toString());
5978c04b90cc95b16f8d7e99a61d8e2c940ed83b0c4Jaikumar Ganesh            Log.v(TAG, "UUID:");
5988c04b90cc95b16f8d7e99a61d8e2c940ed83b0c4Jaikumar Ganesh            for (int i = 0; i < uuids.length; i++) {
5998c04b90cc95b16f8d7e99a61d8e2c940ed83b0c4Jaikumar Ganesh                Log.v(TAG, "  " + uuids[i]);
6002aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan            }
601b20dd917e2d29045225985baa980a2a8e22e10fcNick Pelly        }
6022aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan        return true;
603afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    }
604afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
605afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    /**
606afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project     * Refreshes the UI for the BT class, including fetching the latest value
607afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project     * for the class.
608afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project     */
609afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    public void refreshBtClass() {
610afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        fetchBtClass();
611afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        dispatchAttributesChanged();
612afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    }
613afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
6142aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan    /**
6152aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan     * Refreshes the UI when framework alerts us of a UUID change.
6162aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan     */
6172aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan    public void onUuidChanged() {
6182aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan        updateProfiles();
6192aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan
620eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan        if (DEBUG) {
621eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan            Log.e(TAG, "onUuidChanged: Time since last connect"
622eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan                    + (SystemClock.elapsedRealtime() - mConnectAttempted));
623eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan        }
6242aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan
6252aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan        /*
6262aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan         * If a connect was attempted earlier without any UUID, we will do the
6272aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan         * connect now.
6282aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan         */
6292aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan        if (mProfiles.size() > 0
630eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan                && (mConnectAttempted + MAX_UUID_DELAY_FOR_AUTO_CONNECT) > SystemClock
6312aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan                        .elapsedRealtime()) {
63239ef225e7c44a48aa9cfdf5c56ecd4ddfb95ae89Jake Hamby            connectWithoutResettingTimer(false);
6332aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan        }
6342aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan        dispatchAttributesChanged();
6352aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan    }
6362aef1f3c814b1f8aa00aeefff35caf293c738702Michael Chan
637eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan    public void onBondingStateChanged(int bondState) {
638eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan        if (bondState == BluetoothDevice.BOND_NONE) {
639eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan            mProfiles.clear();
640dd79a33ba53fec530094f4d2fe37f0538530d9f8Jake Hamby            mConnectAfterPairing = false;  // cancel auto-connect
641eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan        }
6421308453b16c2ca85a456bd4bb7f3c71c916bd83eMichael Chan
643eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan        refresh();
644dd79a33ba53fec530094f4d2fe37f0538530d9f8Jake Hamby
645dd79a33ba53fec530094f4d2fe37f0538530d9f8Jake Hamby        if (bondState == BluetoothDevice.BOND_BONDED) {
646dd79a33ba53fec530094f4d2fe37f0538530d9f8Jake Hamby            if (mDevice.isBluetoothDock()) {
647dd79a33ba53fec530094f4d2fe37f0538530d9f8Jake Hamby                onBondingDockConnect();
648dd79a33ba53fec530094f4d2fe37f0538530d9f8Jake Hamby            } else if (mConnectAfterPairing) {
649dd79a33ba53fec530094f4d2fe37f0538530d9f8Jake Hamby                connect();
650dd79a33ba53fec530094f4d2fe37f0538530d9f8Jake Hamby            }
651dd79a33ba53fec530094f4d2fe37f0538530d9f8Jake Hamby            mConnectAfterPairing = false;
652dd79a33ba53fec530094f4d2fe37f0538530d9f8Jake Hamby        }
653eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan    }
654eaf13a2c154a0c7bf7559b45d33fb589b5bcf3d4Michael Chan
65516cc86315d7a8e1f6a0f3083d0a810a7cb097832Nick Pelly    public void setBtClass(BluetoothClass btClass) {
65616cc86315d7a8e1f6a0f3083d0a810a7cb097832Nick Pelly        if (btClass != null && mBtClass != btClass) {
657d97daa064b35ee0c2b73547d46f97fa88d2da4e9Jaikumar Ganesh            mBtClass = btClass;
658d97daa064b35ee0c2b73547d46f97fa88d2da4e9Jaikumar Ganesh            dispatchAttributesChanged();
659d97daa064b35ee0c2b73547d46f97fa88d2da4e9Jaikumar Ganesh        }
660d97daa064b35ee0c2b73547d46f97fa88d2da4e9Jaikumar Ganesh    }
661d97daa064b35ee0c2b73547d46f97fa88d2da4e9Jaikumar Ganesh
662c090feb64f674d9840993736a24f9667f8b0e0d5Jake Hamby    public int getSummary() {
663afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        for (Profile profile : mProfiles) {
664afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            LocalBluetoothProfileManager profileManager = LocalBluetoothProfileManager
665afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                    .getProfileManager(mLocalManager, profile);
666d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly            int connectionStatus = profileManager.getConnectionStatus(mDevice);
667afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
668afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            if (SettingsBtStatus.isConnectionStatusConnected(connectionStatus) ||
669afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                    connectionStatus == SettingsBtStatus.CONNECTION_STATUS_CONNECTING ||
670afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                    connectionStatus == SettingsBtStatus.CONNECTION_STATUS_DISCONNECTING) {
671afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                return SettingsBtStatus.getConnectionStatusSummary(connectionStatus);
672afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            }
673afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        }
674afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
675afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        return SettingsBtStatus.getPairingStatusSummary(getBondState());
676afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    }
677afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
678c090feb64f674d9840993736a24f9667f8b0e0d5Jake Hamby    public Map<Profile, Drawable> getProfileIcons() {
679c090feb64f674d9840993736a24f9667f8b0e0d5Jake Hamby        Map<Profile, Drawable> drawables = new HashMap<Profile, Drawable>();
68048e90002839e662eb1667471aebeb0483e9fb7dbAmith Yamasani
68148e90002839e662eb1667471aebeb0483e9fb7dbAmith Yamasani        for (Profile profile : mProfiles) {
68248e90002839e662eb1667471aebeb0483e9fb7dbAmith Yamasani            LocalBluetoothProfileManager profileManager = LocalBluetoothProfileManager
68348e90002839e662eb1667471aebeb0483e9fb7dbAmith Yamasani                    .getProfileManager(mLocalManager, profile);
68448e90002839e662eb1667471aebeb0483e9fb7dbAmith Yamasani            int iconResource = profileManager.getDrawableResource();
68548e90002839e662eb1667471aebeb0483e9fb7dbAmith Yamasani            if (iconResource != 0) {
686c090feb64f674d9840993736a24f9667f8b0e0d5Jake Hamby                drawables.put(profile, mContext.getResources().getDrawable(iconResource));
68748e90002839e662eb1667471aebeb0483e9fb7dbAmith Yamasani            }
68848e90002839e662eb1667471aebeb0483e9fb7dbAmith Yamasani        }
68948e90002839e662eb1667471aebeb0483e9fb7dbAmith Yamasani
69048e90002839e662eb1667471aebeb0483e9fb7dbAmith Yamasani        return drawables;
69148e90002839e662eb1667471aebeb0483e9fb7dbAmith Yamasani    }
692afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
693e6531e253bf646324d3a68de0e9cc612c5e1c8acMichael Chan    public List<Profile> getConnectableProfiles() {
694e6531e253bf646324d3a68de0e9cc612c5e1c8acMichael Chan        ArrayList<Profile> connectableProfiles = new ArrayList<Profile>();
695e6531e253bf646324d3a68de0e9cc612c5e1c8acMichael Chan        for (Profile profile : mProfiles) {
69639ef225e7c44a48aa9cfdf5c56ecd4ddfb95ae89Jake Hamby            if (profile.isConnectable()) {
697e6531e253bf646324d3a68de0e9cc612c5e1c8acMichael Chan                connectableProfiles.add(profile);
698e6531e253bf646324d3a68de0e9cc612c5e1c8acMichael Chan            }
699e6531e253bf646324d3a68de0e9cc612c5e1c8acMichael Chan        }
700e6531e253bf646324d3a68de0e9cc612c5e1c8acMichael Chan        return connectableProfiles;
701e6531e253bf646324d3a68de0e9cc612c5e1c8acMichael Chan    }
702e6531e253bf646324d3a68de0e9cc612c5e1c8acMichael Chan
70348e90002839e662eb1667471aebeb0483e9fb7dbAmith Yamasani    public void onClickedAdvancedOptions(SettingsPreferenceFragment fragment) {
70448e90002839e662eb1667471aebeb0483e9fb7dbAmith Yamasani        // TODO: Verify if there really is a case when there's no foreground
70548e90002839e662eb1667471aebeb0483e9fb7dbAmith Yamasani        // activity
70648e90002839e662eb1667471aebeb0483e9fb7dbAmith Yamasani
70748e90002839e662eb1667471aebeb0483e9fb7dbAmith Yamasani        // Intent intent = new Intent();
70848e90002839e662eb1667471aebeb0483e9fb7dbAmith Yamasani        // // Need an activity context to open this in our task
70948e90002839e662eb1667471aebeb0483e9fb7dbAmith Yamasani        // Context context = mLocalManager.getForegroundActivity();
71048e90002839e662eb1667471aebeb0483e9fb7dbAmith Yamasani        // if (context == null) {
71148e90002839e662eb1667471aebeb0483e9fb7dbAmith Yamasani        // // Fallback on application context, and open in a new task
71248e90002839e662eb1667471aebeb0483e9fb7dbAmith Yamasani        // context = mLocalManager.getContext();
71348e90002839e662eb1667471aebeb0483e9fb7dbAmith Yamasani        // intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
71448e90002839e662eb1667471aebeb0483e9fb7dbAmith Yamasani        // }
71548e90002839e662eb1667471aebeb0483e9fb7dbAmith Yamasani        // intent.setClass(context, ConnectSpecificProfilesActivity.class);
71648e90002839e662eb1667471aebeb0483e9fb7dbAmith Yamasani        // intent.putExtra(ConnectSpecificProfilesActivity.EXTRA_DEVICE,
71748e90002839e662eb1667471aebeb0483e9fb7dbAmith Yamasani        // mDevice);
71848e90002839e662eb1667471aebeb0483e9fb7dbAmith Yamasani        // context.startActivity(intent);
71948e90002839e662eb1667471aebeb0483e9fb7dbAmith Yamasani        Preference pref = new Preference(fragment.getActivity());
72048e90002839e662eb1667471aebeb0483e9fb7dbAmith Yamasani        pref.setTitle(getName());
72148e90002839e662eb1667471aebeb0483e9fb7dbAmith Yamasani        pref.setFragment(DeviceProfilesSettings.class.getName());
72248e90002839e662eb1667471aebeb0483e9fb7dbAmith Yamasani        pref.getExtras().putParcelable(DeviceProfilesSettings.EXTRA_DEVICE, mDevice);
72348e90002839e662eb1667471aebeb0483e9fb7dbAmith Yamasani        ((PreferenceActivity) fragment.getActivity()).onPreferenceStartFragment(fragment, pref);
72448e90002839e662eb1667471aebeb0483e9fb7dbAmith Yamasani    }
72548e90002839e662eb1667471aebeb0483e9fb7dbAmith Yamasani
726afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    public void registerCallback(Callback callback) {
727afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        synchronized (mCallbacks) {
728afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            mCallbacks.add(callback);
729afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        }
730afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    }
731afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
732afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    public void unregisterCallback(Callback callback) {
733afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        synchronized (mCallbacks) {
734afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            mCallbacks.remove(callback);
735afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        }
736afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    }
737afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
738afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    private void dispatchAttributesChanged() {
739afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        synchronized (mCallbacks) {
740afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            for (Callback callback : mCallbacks) {
741c090feb64f674d9840993736a24f9667f8b0e0d5Jake Hamby                callback.onDeviceAttributesChanged();
742afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            }
743afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        }
744afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    }
745afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
746afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    @Override
747afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    public String toString() {
748d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly        return mDevice.toString();
749afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    }
750afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
751afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    @Override
752afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    public boolean equals(Object o) {
753d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly        if ((o == null) || !(o instanceof CachedBluetoothDevice)) {
754afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            throw new ClassCastException();
755afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        }
756afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
757d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly        return mDevice.equals(((CachedBluetoothDevice) o).mDevice);
758afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    }
759afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
760afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    @Override
761afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    public int hashCode() {
762d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly        return mDevice.getAddress().hashCode();
763afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    }
764afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
765d63c0112251ab4e4e977545368dd703d875012a4Nick Pelly    public int compareTo(CachedBluetoothDevice another) {
766afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        int comparison;
767afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
768afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        // Connected above not connected
769afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        comparison = (another.isConnected() ? 1 : 0) - (isConnected() ? 1 : 0);
770afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        if (comparison != 0) return comparison;
771afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
772afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        // Paired above not paired
773afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        comparison = (another.getBondState() == BluetoothDevice.BOND_BONDED ? 1 : 0) -
774afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            (getBondState() == BluetoothDevice.BOND_BONDED ? 1 : 0);
775afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        if (comparison != 0) return comparison;
776afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
777afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        // Visible above not visible
778afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        comparison = (another.mVisible ? 1 : 0) - (mVisible ? 1 : 0);
779afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        if (comparison != 0) return comparison;
780afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
781afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        // Stronger signal above weaker signal
782afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        comparison = another.mRssi - mRssi;
783afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        if (comparison != 0) return comparison;
784afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
785afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        // Fallback on name
786afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        return getName().compareTo(another.getName());
787afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    }
788afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
789afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    public interface Callback {
790c090feb64f674d9840993736a24f9667f8b0e0d5Jake Hamby        void onDeviceAttributesChanged();
791afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    }
792afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project}
793