BluetoothService.java revision 2d3b98d868cda30535505b2a2fba47aa1c9c052b
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License.
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License.
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * TODO: Move this to
19bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly * java/services/com/android/server/BluetoothService.java
209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * and make the contructor package private again.
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @hide
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.server;
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
27bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pellyimport android.bluetooth.BluetoothAdapter;
28dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganeshimport android.bluetooth.BluetoothClass;
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.bluetooth.BluetoothDevice;
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.bluetooth.BluetoothHeadset;
3110eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganeshimport android.bluetooth.BluetoothUuid;
32bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pellyimport android.bluetooth.IBluetooth;
33dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganeshimport android.bluetooth.ParcelUuid;
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.BroadcastReceiver;
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.ContentResolver;
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context;
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Intent;
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.IntentFilter;
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Binder;
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Handler;
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Message;
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.RemoteException;
43105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Projectimport android.os.ServiceManager;
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.SystemService;
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.provider.Settings;
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log;
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
48d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganeshimport com.android.internal.app.IBatteryStats;
49d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.FileDescriptor;
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.PrintWriter;
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.UnsupportedEncodingException;
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.ArrayList;
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Arrays;
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.HashMap;
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Map;
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
58bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pellypublic class BluetoothService extends IBluetooth.Stub {
59bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly    private static final String TAG = "BluetoothService";
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final boolean DBG = true;
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mNativeData;
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private BluetoothEventLoop mEventLoop;
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private IntentFilter mIntentFilter;
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mIsAirplaneSensitive;
66105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    private int mBluetoothState;
67997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly    private boolean mRestart = false;  // need to call enable() after disable()
68bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly    private boolean mIsDiscovering;
69997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly
70bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly    private BluetoothAdapter mAdapter;  // constant after init()
71997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly    private final BondState mBondState = new BondState();  // local cache of bondings
72105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    private final IBatteryStats mBatteryStats;
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final Context mContext;
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String BLUETOOTH_ADMIN_PERM = android.Manifest.permission.BLUETOOTH_ADMIN;
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String BLUETOOTH_PERM = android.Manifest.permission.BLUETOOTH;
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
78105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    private static final int MESSAGE_REGISTER_SDP_RECORDS = 1;
79105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    private static final int MESSAGE_FINISH_DISABLE = 2;
801caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh    private static final int MESSAGE_UUID_INTENT = 3;
811caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh
821caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh    // The timeout used to sent the UUIDs Intent
831caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh    // This timeout should be greater than the page timeout
841caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh    private static final int UUID_INTENT_DELAY = 6000;
85105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
86bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly    private final Map<String, String> mAdapterProperties;
87bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly    private final HashMap <String, Map<String, String>> mDeviceProperties;
88d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh
8910eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh    private final HashMap <String, Map<ParcelUuid, Integer>> mDeviceServiceChannelCache;
901caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh    private final ArrayList <String> mUuidIntentTracker;
911caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static {
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        classInitNative();
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
96bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly    public BluetoothService(Context context) {
979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext = context;
98105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
99105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        // Need to do this in place of:
100105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        // mBatteryStats = BatteryStatsService.getService();
101105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        // Since we can not import BatteryStatsService from here. This class really needs to be
102105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        // moved to java/services/com/android/server/
103105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        mBatteryStats = IBatteryStats.Stub.asInterface(ServiceManager.getService("batteryinfo"));
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        initializeNativeDataNative();
106ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project
107ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project        if (isEnabledNative() == 1) {
108ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project            Log.w(TAG, "Bluetooth daemons already running - runtime restart? ");
109ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project            disableNative();
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
111ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project
112de893f550301a60274e87aa8168225e7a7a42184Nick Pelly        mBluetoothState = BluetoothAdapter.STATE_OFF;
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mIsDiscovering = false;
114bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly        mAdapterProperties = new HashMap<String, String>();
115bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly        mDeviceProperties = new HashMap<String, Map<String,String>>();
11610eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh
11710eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh        mDeviceServiceChannelCache = new HashMap<String, Map<ParcelUuid, Integer>>();
1181caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh        mUuidIntentTracker = new ArrayList<String>();
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        registerForAirplaneMode();
120bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly    }
121bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly
122bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly    public synchronized void initAfterRegistration() {
123bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly        mAdapter = (BluetoothAdapter) mContext.getSystemService(Context.BLUETOOTH_SERVICE);
124bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly        mEventLoop = new BluetoothEventLoop(mContext, mAdapter, this);
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected void finalize() throws Throwable {
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mIsAirplaneSensitive) {
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mContext.unregisterReceiver(mReceiver);
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            cleanupNativeDataNative();
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } finally {
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            super.finalize();
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean isEnabled() {
1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
141de893f550301a60274e87aa8168225e7a7a42184Nick Pelly        return mBluetoothState == BluetoothAdapter.STATE_ON;
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
144105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    public int getBluetoothState() {
145105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
146105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        return mBluetoothState;
147105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    }
148105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
149105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Bring down bluetooth and disable BT in settings. Returns true on success.
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean disable() {
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return disable(true);
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Bring down bluetooth. Returns true on success.
1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param saveSetting If true, disable BT in settings
1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public synchronized boolean disable(boolean saveSetting) {
163d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
165105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        switch (mBluetoothState) {
166de893f550301a60274e87aa8168225e7a7a42184Nick Pelly        case BluetoothAdapter.STATE_OFF:
167105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            return true;
168de893f550301a60274e87aa8168225e7a7a42184Nick Pelly        case BluetoothAdapter.STATE_ON:
169105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            break;
170105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        default:
171105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            return false;
172105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        }
1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mEnableThread != null && mEnableThread.isAlive()) {
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
176de893f550301a60274e87aa8168225e7a7a42184Nick Pelly        setBluetoothState(BluetoothAdapter.STATE_TURNING_OFF);
177105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
178105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        // Allow 3 seconds for profiles to gracefully disconnect
179105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        // TODO: Introduce a callback mechanism so that each profile can notify
180bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly        // BluetoothService when it is done shutting down
181105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        mHandler.sendMessageDelayed(
182105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                mHandler.obtainMessage(MESSAGE_FINISH_DISABLE, saveSetting ? 1 : 0, 0), 3000);
183105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        return true;
184105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    }
185105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
186105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
187105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    private synchronized void finishDisable(boolean saveSetting) {
188de893f550301a60274e87aa8168225e7a7a42184Nick Pelly        if (mBluetoothState != BluetoothAdapter.STATE_TURNING_OFF) {
189105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            return;
1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mEventLoop.stop();
192d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        tearDownNativeDataNative();
1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        disableNative();
1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // mark in progress bondings as cancelled
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (String address : mBondState.listInState(BluetoothDevice.BOND_BONDING)) {
197005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly            mBondState.setBondState(address, BluetoothDevice.BOND_NONE,
1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                    BluetoothDevice.UNBOND_REASON_AUTH_CANCELED);
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // update mode
202de893f550301a60274e87aa8168225e7a7a42184Nick Pelly        Intent intent = new Intent(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED);
203de893f550301a60274e87aa8168225e7a7a42184Nick Pelly        intent.putExtra(BluetoothAdapter.EXTRA_SCAN_MODE, BluetoothAdapter.SCAN_MODE_NONE);
2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext.sendBroadcast(intent, BLUETOOTH_PERM);
2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
206105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        mIsDiscovering = false;
207bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly        mAdapterProperties.clear();
208105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (saveSetting) {
2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            persistBluetoothOnSetting(false);
2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
212105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
213de893f550301a60274e87aa8168225e7a7a42184Nick Pelly        setBluetoothState(BluetoothAdapter.STATE_OFF);
214105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
215105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        // Log bluetooth off to battery stats.
216105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        long ident = Binder.clearCallingIdentity();
217105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        try {
218105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            mBatteryStats.noteBluetoothOff();
219105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        } catch (RemoteException e) {
220105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        } finally {
221105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            Binder.restoreCallingIdentity(ident);
222105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        }
223997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly
224997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly        if (mRestart) {
225997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly            mRestart = false;
226997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly            enable();
227997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly        }
2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
230105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    /** Bring up BT and persist BT on in settings */
231105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    public boolean enable() {
232105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        return enable(true);
2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Enable this Bluetooth device, asynchronously.
2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * This turns on/off the underlying hardware.
2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
239105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project     * @param saveSetting If true, persist the new state of BT in settings
240105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project     * @return True on success (so far)
2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
242105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    public synchronized boolean enable(boolean saveSetting) {
2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                                "Need BLUETOOTH_ADMIN permission");
2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Airplane mode can prevent Bluetooth radio from being turned on.
2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mIsAirplaneSensitive && isAirplaneModeOn()) {
2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
250de893f550301a60274e87aa8168225e7a7a42184Nick Pelly        if (mBluetoothState != BluetoothAdapter.STATE_OFF) {
2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mEnableThread != null && mEnableThread.isAlive()) {
2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
256de893f550301a60274e87aa8168225e7a7a42184Nick Pelly        setBluetoothState(BluetoothAdapter.STATE_TURNING_ON);
257105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        mEnableThread = new EnableThread(saveSetting);
2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mEnableThread.start();
2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return true;
2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
262997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly    /** Forcibly restart Bluetooth if it is on */
263997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly    /* package */ synchronized void restart() {
264de893f550301a60274e87aa8168225e7a7a42184Nick Pelly        if (mBluetoothState != BluetoothAdapter.STATE_ON) {
265997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly            return;
266997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly        }
267997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly        mRestart = true;
268997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly        if (!disable(false)) {
269997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly            mRestart = false;
270997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly        }
271d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh    }
272997c7612a8cf63748165144b423ff2ae8e73c3e9Nick Pelly
273105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    private synchronized void setBluetoothState(int state) {
274105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        if (state == mBluetoothState) {
275105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            return;
276105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        }
277105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
278105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        if (DBG) log("Bluetooth state " + mBluetoothState + " -> " + state);
279105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
280de893f550301a60274e87aa8168225e7a7a42184Nick Pelly        Intent intent = new Intent(BluetoothAdapter.ACTION_STATE_CHANGED);
281de893f550301a60274e87aa8168225e7a7a42184Nick Pelly        intent.putExtra(BluetoothAdapter.EXTRA_PREVIOUS_STATE, mBluetoothState);
282de893f550301a60274e87aa8168225e7a7a42184Nick Pelly        intent.putExtra(BluetoothAdapter.EXTRA_STATE, state);
283105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
284105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
285105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        mBluetoothState = state;
286105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
287105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        mContext.sendBroadcast(intent, BLUETOOTH_PERM);
288105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    }
289105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final Handler mHandler = new Handler() {
2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void handleMessage(Message msg) {
2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            switch (msg.what) {
294105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            case MESSAGE_REGISTER_SDP_RECORDS:
2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                //TODO: Don't assume HSP/HFP is running, don't use sdptool,
2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (isEnabled()) {
2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    SystemService.start("hsag");
2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    SystemService.start("hfag");
29903c707ab6fc97e99b1603b8d6edc604dbea3cd6fNick Pelly                    SystemService.start("opush");
30067542964876aa7e4216e8f69f21dda68e7463b9aJaikumar Ganesh                    SystemService.start("pbap");
3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
302105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                break;
303105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            case MESSAGE_FINISH_DISABLE:
304105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                finishDisable(msg.arg1 != 0);
305105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                break;
3061caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh            case MESSAGE_UUID_INTENT:
3071caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh                String address = (String)msg.obj;
3081caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh                if (address != null)
3091caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh                    sendUuidIntent(address);
3101caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh                break;
3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    };
3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private EnableThread mEnableThread;
3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private class EnableThread extends Thread {
3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private final boolean mSaveSetting;
319105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        public EnableThread(boolean saveSetting) {
3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mSaveSetting = saveSetting;
3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void run() {
3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            boolean res = (enableNative() == 0);
3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (res) {
325b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project                int retryCount = 2;
326b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project                boolean running = false;
327b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project                while ((retryCount-- > 0) && !running) {
328b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project                    mEventLoop.start();
329105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                    // it may take a momement for the other thread to do its
330b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project                    // thing.  Check periodically for a while.
331b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project                    int pollCount = 5;
332b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project                    while ((pollCount-- > 0) && !running) {
333b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project                        if (mEventLoop.isEventLoopRunning()) {
334b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project                            running = true;
335b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project                            break;
336b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project                        }
337b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project                        try {
338b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project                            Thread.sleep(100);
339b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project                        } catch (InterruptedException e) {}
340b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project                    }
341b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project                }
342b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project                if (!running) {
343b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project                    log("bt EnableThread giving up");
344b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project                    res = false;
345b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project                    disableNative();
346b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project                }
3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (res) {
351d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh                if (!setupNativeDataNative()) {
352d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh                    return;
353d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh                }
3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (mSaveSetting) {
3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    persistBluetoothOnSetting(true);
3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mIsDiscovering = false;
3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mBondState.loadBondState();
359105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                mHandler.sendMessageDelayed(mHandler.obtainMessage(MESSAGE_REGISTER_SDP_RECORDS),
360105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                                            3000);
3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
362105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                // Log bluetooth on to battery stats.
363105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                long ident = Binder.clearCallingIdentity();
364105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                try {
365105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                    mBatteryStats.noteBluetoothOn();
366105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                } catch (RemoteException e) {
367105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                } finally {
368105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                    Binder.restoreCallingIdentity(ident);
369105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                }
3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
371105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
372105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            mEnableThread = null;
373105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
374105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            setBluetoothState(res ?
375de893f550301a60274e87aa8168225e7a7a42184Nick Pelly                              BluetoothAdapter.STATE_ON :
376de893f550301a60274e87aa8168225e7a7a42184Nick Pelly                              BluetoothAdapter.STATE_OFF);
377105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
378b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project            if (res) {
379105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                // Update mode
380d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh                String[] propVal = {"Pairable", getProperty("Pairable")};
381d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh                mEventLoop.onPropertyChanged(propVal);
382b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project            }
383b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project
3845c43f735d94a538dc273c8f859d1100a7cdd5c71Daisuke Miyakawa            if (mIsAirplaneSensitive && isAirplaneModeOn()) {
3855c43f735d94a538dc273c8f859d1100a7cdd5c71Daisuke Miyakawa                disable(false);
3865c43f735d94a538dc273c8f859d1100a7cdd5c71Daisuke Miyakawa            }
3875c43f735d94a538dc273c8f859d1100a7cdd5c71Daisuke Miyakawa
3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void persistBluetoothOnSetting(boolean bluetoothOn) {
3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        long origCallerIdentityToken = Binder.clearCallingIdentity();
3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Settings.Secure.putInt(mContext.getContentResolver(), Settings.Secure.BLUETOOTH_ON,
3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                bluetoothOn ? 1 : 0);
3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Binder.restoreCallingIdentity(origCallerIdentityToken);
3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /* package */ BondState getBondState() {
3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mBondState;
4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** local cache of bonding state.
4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /* we keep our own state to track the intermediate state BONDING, which
4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /* bluez does not track.
4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * All addreses must be passed in upper case.
4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public class BondState {
4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private final HashMap<String, Integer> mState = new HashMap<String, Integer>();
4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private final HashMap<String, Integer> mPinAttempt = new HashMap<String, Integer>();
4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private final ArrayList<String> mAutoPairingFailures = new ArrayList<String>();
411105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        // List of all the vendor_id prefix of Bluetooth addresses for
412105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        // which auto pairing is not attempted.
413105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        // The following companies are included in the list below:
414105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        // ALPS (lexus), Murata (Prius 2007, Nokia 616), TEMIC SDS (Porsche, Audi),
415105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        // Parrot, Zhongshan General K-mate Electronics, Great Well
416105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        // Electronics, Flaircomm Electronics, Jatty Electronics, Delphi,
417105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        // Clarion, Novero, Denso (Lexus, Toyota), Johnson Controls (Acura),
418adbaef234e1bd7bbec561fb6291bae394a412ce8Nick Pelly        // Continental Automotive, Harman/Becker, Panasonic/Kyushu Ten
419482d54bb0cd9e00fd929185c31fea3ad845d97bcJaikumar Ganesh        private final ArrayList<String>  mAutoPairingAddressBlacklist =
4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                new ArrayList<String>(Arrays.asList(
421105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                        "00:02:C7", "00:16:FE", "00:19:C1", "00:1B:FB", "00:1E:3D", "00:21:4F",
422105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                        "00:23:06", "00:24:33", "00:A0:79", "00:0E:6D", "00:13:E0", "00:21:E8",
423105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                        "00:60:57", "00:0E:9F", "00:12:1C", "00:18:91", "00:18:96", "00:13:04",
424105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                        "00:16:FD", "00:22:A0", "00:0B:4C", "00:60:6F", "00:23:3D", "00:C0:59",
425adbaef234e1bd7bbec561fb6291bae394a412ce8Nick Pelly                        "00:0A:30", "00:1E:AE", "00:1C:D7", "00:80:F0"
4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        ));
4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
428482d54bb0cd9e00fd929185c31fea3ad845d97bcJaikumar Ganesh        // List of names of Bluetooth devices for which auto pairing should be
429482d54bb0cd9e00fd929185c31fea3ad845d97bcJaikumar Ganesh        // disabled.
430482d54bb0cd9e00fd929185c31fea3ad845d97bcJaikumar Ganesh        private final ArrayList<String> mAutoPairingNameBlacklist =
431482d54bb0cd9e00fd929185c31fea3ad845d97bcJaikumar Ganesh                new ArrayList<String>(Arrays.asList(
432482d54bb0cd9e00fd929185c31fea3ad845d97bcJaikumar Ganesh                        "Motorola IHF1000", "i.TechBlueBAND", "X5 Stereo v1.3"));
433482d54bb0cd9e00fd929185c31fea3ad845d97bcJaikumar Ganesh
4342092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh        // If this is an outgoing connection, store the address.
4352092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh        // There can be only 1 pending outgoing connection at a time,
4362092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh        private String mPendingOutgoingBonding;
4372092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh
4382092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh        private synchronized void setPendingOutgoingBonding(String address) {
4392092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh            mPendingOutgoingBonding = address;
4402092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh        }
4412092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh
4422092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh        public synchronized String getPendingOutgoingBonding() {
4432092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh            return mPendingOutgoingBonding;
4442092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh        }
4452092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh
4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public synchronized void loadBondState() {
447de893f550301a60274e87aa8168225e7a7a42184Nick Pelly            if (mBluetoothState != BluetoothAdapter.STATE_TURNING_ON) {
4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return;
4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
450d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh            String []bonds = null;
451d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh            String val = getProperty("Devices");
452d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh            if (val != null) {
453d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh                bonds = val.split(",");
454d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh            }
4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (bonds == null) {
4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return;
4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mState.clear();
4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (DBG) log("found " + bonds.length + " bonded devices");
460d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh            for (String device : bonds) {
461d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh                mState.put(getAddressFromObjectPath(device).toUpperCase(),
462d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh                        BluetoothDevice.BOND_BONDED);
4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public synchronized void setBondState(String address, int state) {
4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            setBondState(address, state, 0);
4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /** reason is ignored unless state == BOND_NOT_BONDED */
4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public synchronized void setBondState(String address, int state, int reason) {
4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int oldState = getBondState(address);
4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (oldState == state) {
4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return;
4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4762092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh
4772092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh            // Check if this was an pending outgoing bonding.
4782092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh            // If yes, reset the state.
4792092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh            if (oldState == BluetoothDevice.BOND_BONDING) {
4802092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh                if (address.equals(mPendingOutgoingBonding)) {
4812092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh                    mPendingOutgoingBonding = null;
4822092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh                }
4832092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh            }
4842092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh
4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (DBG) log(address + " bond state " + oldState + " -> " + state + " (" +
4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                         reason + ")");
487005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly            Intent intent = new Intent(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
488005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly            intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mAdapter.getRemoteDevice(address));
489005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly            intent.putExtra(BluetoothDevice.EXTRA_BOND_STATE, state);
490005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly            intent.putExtra(BluetoothDevice.EXTRA_PREVIOUS_BOND_STATE, oldState);
491005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly            if (state == BluetoothDevice.BOND_NONE) {
4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (reason <= 0) {
4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    Log.w(TAG, "setBondState() called to unbond device, but reason code is " +
4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                          "invalid. Overriding reason code with BOND_RESULT_REMOVED");
4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    reason = BluetoothDevice.UNBOND_REASON_REMOVED;
4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
497005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly                intent.putExtra(BluetoothDevice.EXTRA_REASON, reason);
4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mState.remove(address);
4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mState.put(address, state);
5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mContext.sendBroadcast(intent, BLUETOOTH_PERM);
5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public boolean isAutoPairingBlacklisted(String address) {
507482d54bb0cd9e00fd929185c31fea3ad845d97bcJaikumar Ganesh            for (String blacklistAddress : mAutoPairingAddressBlacklist) {
5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (address.startsWith(blacklistAddress)) return true;
5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
510482d54bb0cd9e00fd929185c31fea3ad845d97bcJaikumar Ganesh
511482d54bb0cd9e00fd929185c31fea3ad845d97bcJaikumar Ganesh            String name = getRemoteName(address);
512482d54bb0cd9e00fd929185c31fea3ad845d97bcJaikumar Ganesh            if (name != null) {
513482d54bb0cd9e00fd929185c31fea3ad845d97bcJaikumar Ganesh                for (String blacklistName : mAutoPairingNameBlacklist) {
514482d54bb0cd9e00fd929185c31fea3ad845d97bcJaikumar Ganesh                    if (name.equals(blacklistName)) return true;
515482d54bb0cd9e00fd929185c31fea3ad845d97bcJaikumar Ganesh                }
516482d54bb0cd9e00fd929185c31fea3ad845d97bcJaikumar Ganesh            }
5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public synchronized int getBondState(String address) {
5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Integer state = mState.get(address);
5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (state == null) {
523005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly                return BluetoothDevice.BOND_NONE;
5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return state.intValue();
5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private synchronized String[] listInState(int state) {
5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ArrayList<String> result = new ArrayList<String>(mState.size());
5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (Map.Entry<String, Integer> e : mState.entrySet()) {
5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (e.getValue().intValue() == state) {
5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    result.add(e.getKey());
5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return result.toArray(new String[result.size()]);
5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public synchronized void addAutoPairingFailure(String address) {
5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (!mAutoPairingFailures.contains(address)) {
5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mAutoPairingFailures.add(address);
5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public synchronized boolean isAutoPairingAttemptsInProgress(String address) {
5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return getAttempt(address) != 0;
5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public synchronized void clearPinAttempts(String address) {
5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mPinAttempt.remove(address);
5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public synchronized boolean hasAutoPairingFailed(String address) {
5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mAutoPairingFailures.contains(address);
5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public synchronized int getAttempt(String address) {
5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Integer attempt = mPinAttempt.get(address);
5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (attempt == null) {
5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return 0;
5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return attempt.intValue();
5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public synchronized void attempt(String address) {
5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Integer attempt = mPinAttempt.get(address);
5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int newAttempt;
5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (attempt == null) {
5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                newAttempt = 1;
5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                newAttempt = attempt.intValue() + 1;
5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mPinAttempt.put(address, new Integer(newAttempt));
5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static String toBondStateString(int bondState) {
5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        switch (bondState) {
579005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly        case BluetoothDevice.BOND_NONE:
5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return "not bonded";
5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        case BluetoothDevice.BOND_BONDING:
5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return "bonding";
5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        case BluetoothDevice.BOND_BONDED:
5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return "bonded";
5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        default:
5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return "??????";
5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5909519ce75f15ba287a641166c1b7ed10f2aa73f74Jaikumar Ganesh    /*package*/ synchronized boolean isAdapterPropertiesEmpty() {
5919519ce75f15ba287a641166c1b7ed10f2aa73f74Jaikumar Ganesh        return mAdapterProperties.isEmpty();
5929519ce75f15ba287a641166c1b7ed10f2aa73f74Jaikumar Ganesh    }
5939519ce75f15ba287a641166c1b7ed10f2aa73f74Jaikumar Ganesh
594d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh    /*package*/synchronized void getAllProperties() {
5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
596bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly        mAdapterProperties.clear();
597d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh
598d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        String properties[] = (String [])getAdapterPropertiesNative();
599d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        // The String Array consists of key-value pairs.
600d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        if (properties == null) {
601d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh            Log.e(TAG, "*Error*: GetAdapterProperties returned NULL");
602d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh            return;
603d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        }
604d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh
6058bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh        for (int i = 0; i < properties.length; i++) {
6068bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh            String name = properties[i];
607efa33676caf5b7a637fad73cd22c9ef23b68cdc2Jaikumar Ganesh            String newValue = null;
6088bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh            int len;
6098bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh            if (name == null) {
6108bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh                Log.e(TAG, "Error:Adapter Property at index" + i + "is null");
6118bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh                continue;
6128bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh            }
6138bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh            if (name.equals("Devices")) {
614efa33676caf5b7a637fad73cd22c9ef23b68cdc2Jaikumar Ganesh                StringBuilder str = new StringBuilder();
6158bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh                len = Integer.valueOf(properties[++i]);
6168bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh                for (int j = 0; j < len; j++) {
617efa33676caf5b7a637fad73cd22c9ef23b68cdc2Jaikumar Ganesh                    str.append(properties[++i]);
618efa33676caf5b7a637fad73cd22c9ef23b68cdc2Jaikumar Ganesh                    str.append(",");
619efa33676caf5b7a637fad73cd22c9ef23b68cdc2Jaikumar Ganesh                }
620efa33676caf5b7a637fad73cd22c9ef23b68cdc2Jaikumar Ganesh                if (len > 0) {
621efa33676caf5b7a637fad73cd22c9ef23b68cdc2Jaikumar Ganesh                    newValue = str.toString();
6228bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh                }
6238bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh            } else {
6248bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh                newValue = properties[++i];
6258bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh            }
626bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly            mAdapterProperties.put(name, newValue);
627d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        }
628d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh
629d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        // Add adapter object path property.
630d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        String adapterPath = getAdapterPathNative();
631d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        if (adapterPath != null)
632bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly            mAdapterProperties.put("ObjectPath", adapterPath + "/dev_");
6339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
635d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh    /* package */ synchronized void setProperty(String name, String value) {
636bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly        mAdapterProperties.put(name, value);
6379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public synchronized boolean setName(String name) {
6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                                "Need BLUETOOTH_ADMIN permission");
6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (name == null) {
6439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
6449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
645d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        return setPropertyString("Name", name);
6469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
648d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh    //TODO(): setPropertyString, setPropertyInteger, setPropertyBoolean
649d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh    // Either have a single property function with Object as the parameter
650d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh    // or have a function for each property and then obfuscate in the JNI layer.
651d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh    // The following looks dirty.
652d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh    private boolean setPropertyString(String key, String value) {
6539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
654d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        return setAdapterPropertyStringNative(key, value);
6559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
657d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh    private boolean setPropertyInteger(String key, int value) {
658d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
659d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        return setAdapterPropertyIntegerNative(key, value);
660d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh    }
6619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
662d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh    private boolean setPropertyBoolean(String key, boolean value) {
663d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
664d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        return setAdapterPropertyBooleanNative(key, value ? 1 : 0);
6659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
667d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh    /**
668d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh     * Set the discoverability window for the device.  A timeout of zero
669d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh     * makes the device permanently discoverable (if the device is
670d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh     * discoverable).  Setting the timeout to a nonzero value does not make
671d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh     * a device discoverable; you need to call setMode() to make the device
672d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh     * explicitly discoverable.
673d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh     *
674d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh     * @param timeout_s The discoverable timeout in seconds.
675d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh     */
676d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh    public synchronized boolean setDiscoverableTimeout(int timeout) {
6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                                "Need BLUETOOTH_ADMIN permission");
679d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        return setPropertyInteger("DiscoverableTimeout", timeout);
6809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
682d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh    public synchronized boolean setScanMode(int mode) {
683d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
684d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh                                                "Need BLUETOOTH_ADMIN permission");
685de893f550301a60274e87aa8168225e7a7a42184Nick Pelly        boolean pairable = false;
686de893f550301a60274e87aa8168225e7a7a42184Nick Pelly        boolean discoverable = false;
687de893f550301a60274e87aa8168225e7a7a42184Nick Pelly        switch (mode) {
688de893f550301a60274e87aa8168225e7a7a42184Nick Pelly        case BluetoothAdapter.SCAN_MODE_NONE:
689d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh            pairable = false;
690d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh            discoverable = false;
691de893f550301a60274e87aa8168225e7a7a42184Nick Pelly            break;
692de893f550301a60274e87aa8168225e7a7a42184Nick Pelly        case BluetoothAdapter.SCAN_MODE_CONNECTABLE:
693d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh            pairable = true;
694d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh            discoverable = false;
695005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly            break;
696de893f550301a60274e87aa8168225e7a7a42184Nick Pelly        case BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE:
697d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh            pairable = true;
698d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh            discoverable = true;
699005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly            break;
700de893f550301a60274e87aa8168225e7a7a42184Nick Pelly        default:
701de893f550301a60274e87aa8168225e7a7a42184Nick Pelly            Log.w(TAG, "Requested invalid scan mode " + mode);
702de893f550301a60274e87aa8168225e7a7a42184Nick Pelly            return false;
703d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        }
704d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        setPropertyBoolean("Pairable", pairable);
705d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        setPropertyBoolean("Discoverable", discoverable);
7069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
707d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        return true;
7089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
710d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh    /*package*/ synchronized String getProperty (String name) {
711bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly        if (!mAdapterProperties.isEmpty())
712bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly            return mAdapterProperties.get(name);
713d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        getAllProperties();
714bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly        return mAdapterProperties.get(name);
7159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
717d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh    public synchronized String getAddress() {
718d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
719d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        return getProperty("Address");
7209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
722d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh    public synchronized String getName() {
7239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
724d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        return getProperty("Name");
7259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
728d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh     * Returns the user-friendly name of a remote device.  This value is
729d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh     * returned from our local cache, which is updated when onPropertyChange
730d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh     * event is received.
731d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh     * Do not expect to retrieve the updated remote name immediately after
732d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh     * changing the name on the remote device.
7339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
734d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh     * @param address Bluetooth address of remote device.
735d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh     *
736d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh     * @return The user-friendly name of the specified remote device.
7379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
738d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh    public synchronized String getRemoteName(String address) {
739d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
740005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly        if (!BluetoothAdapter.checkBluetoothAddress(address)) {
741d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh            return null;
742d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        }
743bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly        Map <String, String> properties = mDeviceProperties.get(address);
744d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        if (properties != null) return properties.get("Name");
745d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        return null;
7469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
7499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Get the discoverability window for the device.  A timeout of zero
7509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * means that the device is permanently discoverable (if the device is
7519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * in the discoverable mode).
7529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
7539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return The discoverability window of the device, in seconds.  A negative
7549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *         value indicates an error.
7559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public synchronized int getDiscoverableTimeout() {
7579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
758d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        String timeout = getProperty("DiscoverableTimeout");
759d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        if (timeout != null)
760d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh           return Integer.valueOf(timeout);
761d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        else
762d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh            return -1;
7639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public synchronized int getScanMode() {
7669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
767d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        if (!isEnabled())
768de893f550301a60274e87aa8168225e7a7a42184Nick Pelly            return BluetoothAdapter.SCAN_MODE_NONE;
769d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh
770d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        boolean pairable = getProperty("Pairable").equals("true");
771d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        boolean discoverable = getProperty("Discoverable").equals("true");
772d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        return bluezStringToScanMode (pairable, discoverable);
7739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
775d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh    public synchronized boolean startDiscovery() {
7769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
7779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                                "Need BLUETOOTH_ADMIN permission");
778d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        if (!isEnabled()) {
779d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh            return false;
7809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
781d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        return startDiscoveryNative();
7829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
784d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh    public synchronized boolean cancelDiscovery() {
7859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
7869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                                "Need BLUETOOTH_ADMIN permission");
787d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        return stopDiscoveryNative();
788d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh    }
789d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh
790d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh    public synchronized boolean isDiscovering() {
791d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
792d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        return mIsDiscovering;
793d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh    }
794d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh
795d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh    /* package */ void setIsDiscovering(boolean isDiscovering) {
796d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        mIsDiscovering = isDiscovering;
7979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public synchronized boolean createBond(String address) {
8009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
8019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                                "Need BLUETOOTH_ADMIN permission");
802005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly        if (!BluetoothAdapter.checkBluetoothAddress(address)) {
8039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
8049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        address = address.toUpperCase();
8069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8072092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh        if (mBondState.getPendingOutgoingBonding() != null) {
8089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            log("Ignoring createBond(): another device is bonding");
8099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // a different device is currently bonding, fail
8109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
8119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Check for bond state only if we are not performing auto
8149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // pairing exponential back-off attempts.
8159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!mBondState.isAutoPairingAttemptsInProgress(address) &&
816005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly                mBondState.getBondState(address) != BluetoothDevice.BOND_NONE) {
8179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            log("Ignoring createBond(): this device is already bonding or bonded");
8189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
8199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
821d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        if (!createPairedDeviceNative(address, 60000 /* 1 minute */)) {
8229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
8239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8252092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh        mBondState.setPendingOutgoingBonding(address);
8269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mBondState.setBondState(address, BluetoothDevice.BOND_BONDING);
8272092361d586a20190c9137fb3cc9434cdc9ec99fJaikumar Ganesh
8289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return true;
8299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public synchronized boolean cancelBondProcess(String address) {
8329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
8339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                                "Need BLUETOOTH_ADMIN permission");
834005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly        if (!BluetoothAdapter.checkBluetoothAddress(address)) {
8359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
8369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        address = address.toUpperCase();
8389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mBondState.getBondState(address) != BluetoothDevice.BOND_BONDING) {
8399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
8409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
842005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly        mBondState.setBondState(address, BluetoothDevice.BOND_NONE,
8439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                BluetoothDevice.UNBOND_REASON_AUTH_CANCELED);
844d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        cancelDeviceCreationNative(address);
8459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return true;
8469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public synchronized boolean removeBond(String address) {
8499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
8509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                                "Need BLUETOOTH_ADMIN permission");
851005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly        if (!BluetoothAdapter.checkBluetoothAddress(address)) {
8529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
8539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
854d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        return removeDeviceNative(getObjectPathFromAddress(address));
8559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public synchronized String[] listBonds() {
8589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
8599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mBondState.listInState(BluetoothDevice.BOND_BONDED);
8609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public synchronized int getBondState(String address) {
8639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
864005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly        if (!BluetoothAdapter.checkBluetoothAddress(address)) {
865b24e11baac589fe16426f2d243b460ab84991c7bNick Pelly            return BluetoothDevice.ERROR;
8669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mBondState.getBondState(address.toUpperCase());
8689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8709488cbd0b9ce0a9b49647910e76c6fa910f948eaJaikumar Ganesh    /*package*/ boolean isRemoteDeviceInCache(String address) {
871bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly        return (mDeviceProperties.get(address) != null);
8729488cbd0b9ce0a9b49647910e76c6fa910f948eaJaikumar Ganesh    }
8739488cbd0b9ce0a9b49647910e76c6fa910f948eaJaikumar Ganesh
8749488cbd0b9ce0a9b49647910e76c6fa910f948eaJaikumar Ganesh    /*package*/ String[] getRemoteDeviceProperties(String address) {
8759488cbd0b9ce0a9b49647910e76c6fa910f948eaJaikumar Ganesh        String objectPath = getObjectPathFromAddress(address);
8769488cbd0b9ce0a9b49647910e76c6fa910f948eaJaikumar Ganesh        return (String [])getDevicePropertiesNative(objectPath);
8779488cbd0b9ce0a9b49647910e76c6fa910f948eaJaikumar Ganesh    }
8789488cbd0b9ce0a9b49647910e76c6fa910f948eaJaikumar Ganesh
879d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh    /*package*/ synchronized String getRemoteDeviceProperty(String address, String property) {
880bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly        Map<String, String> properties = mDeviceProperties.get(address);
881d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        if (properties != null) {
882d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh            return properties.get(property);
883d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        } else {
884d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh            // Query for remote device properties, again.
885d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh            // We will need to reload the cache when we switch Bluetooth on / off
886d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh            // or if we crash.
88710eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh            if (updateRemoteDevicePropertiesCache(address))
888d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh                return getRemoteDeviceProperty(address, property);
8899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
890d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        Log.e(TAG, "getRemoteDeviceProperty: " + property + "not present:" + address);
891d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        return null;
8929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
89410eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh    /* package */ synchronized boolean updateRemoteDevicePropertiesCache(String address) {
89510eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh        String[] propValues = getRemoteDeviceProperties(address);
89610eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh        if (propValues != null) {
89710eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh            addRemoteDeviceProperties(address, propValues);
89810eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh            return true;
89910eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh        }
90010eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh        return false;
90110eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh    }
90210eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh
903d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh    /* package */ synchronized void addRemoteDeviceProperties(String address, String[] properties) {
904395d1023660c5caedf7888def17f8ad826f51bf8Jaikumar Ganesh        /*
905395d1023660c5caedf7888def17f8ad826f51bf8Jaikumar Ganesh         * We get a DeviceFound signal every time RSSI changes or name changes.
906395d1023660c5caedf7888def17f8ad826f51bf8Jaikumar Ganesh         * Don't create a new Map object every time */
907bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly        Map<String, String> propertyValues = mDeviceProperties.get(address);
908efa33676caf5b7a637fad73cd22c9ef23b68cdc2Jaikumar Ganesh        if (propertyValues == null) {
909395d1023660c5caedf7888def17f8ad826f51bf8Jaikumar Ganesh            propertyValues = new HashMap<String, String>();
910395d1023660c5caedf7888def17f8ad826f51bf8Jaikumar Ganesh        }
911395d1023660c5caedf7888def17f8ad826f51bf8Jaikumar Ganesh
9128bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh        for (int i = 0; i < properties.length; i++) {
9138bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh            String name = properties[i];
914efa33676caf5b7a637fad73cd22c9ef23b68cdc2Jaikumar Ganesh            String newValue = null;
9158bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh            int len;
9168bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh            if (name == null) {
9178bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh                Log.e(TAG, "Error: Remote Device Property at index" + i + "is null");
9188bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh                continue;
9198bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh            }
9208bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh            if (name.equals("UUIDs") || name.equals("Nodes")) {
921efa33676caf5b7a637fad73cd22c9ef23b68cdc2Jaikumar Ganesh                StringBuilder str = new StringBuilder();
9228bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh                len = Integer.valueOf(properties[++i]);
9238bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh                for (int j = 0; j < len; j++) {
924efa33676caf5b7a637fad73cd22c9ef23b68cdc2Jaikumar Ganesh                    str.append(properties[++i]);
925efa33676caf5b7a637fad73cd22c9ef23b68cdc2Jaikumar Ganesh                    str.append(",");
926efa33676caf5b7a637fad73cd22c9ef23b68cdc2Jaikumar Ganesh                }
927efa33676caf5b7a637fad73cd22c9ef23b68cdc2Jaikumar Ganesh                if (len > 0) {
928efa33676caf5b7a637fad73cd22c9ef23b68cdc2Jaikumar Ganesh                    newValue = str.toString();
9298bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh                }
930d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh            } else {
9318bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh                newValue = properties[++i];
932d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh            }
933efa33676caf5b7a637fad73cd22c9ef23b68cdc2Jaikumar Ganesh
9348bc8ce44f7e5a720e7b989bdd63bb33da512103bJaikumar Ganesh            propertyValues.put(name, newValue);
9359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
936bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly        mDeviceProperties.put(address, propertyValues);
93710eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh
93810eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh        // We have added a new remote device or updated its properties.
93910eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh        // Also update the serviceChannel cache.
94010eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh        updateDeviceServiceChannelCache(address);
9419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
943d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh    /* package */ void removeRemoteDeviceProperties(String address) {
944bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly        mDeviceProperties.remove(address);
9459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
947d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh    /* package */ synchronized void setRemoteDeviceProperty(String address, String name,
948d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh                                                              String value) {
949bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly        Map <String, String> propVal = mDeviceProperties.get(address);
950d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        if (propVal != null) {
951d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh            propVal.put(name, value);
952bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly            mDeviceProperties.put(address, propVal);
953d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        } else {
954d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh            Log.e(TAG, "setRemoteDeviceProperty for a device not in cache:" + address);
9559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
959efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue     * Sets the remote device trust state.
960efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue     *
961efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue     * @return boolean to indicate operation success or fail
962efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue     */
963efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue    public synchronized boolean setTrust(String address, boolean value) {
964005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly        if (!BluetoothAdapter.checkBluetoothAddress(address)) {
965efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue            mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
966efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue            return false;
967efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue        }
968efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue
969efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue        return setDevicePropertyBooleanNative(getObjectPathFromAddress(address), "Trusted",
970efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue                value ? 1 : 0);
971efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue    }
972efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue
973efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue    /**
974efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue     * Gets the remote device trust state as boolean.
975efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue     * Note: this value may be
976efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue     * retrieved from cache if we retrieved the data before *
977efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue     *
978efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue     * @return boolean to indicate trust or untrust state
979efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue     */
980efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue    public synchronized boolean getTrustState(String address) {
981005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly        if (!BluetoothAdapter.checkBluetoothAddress(address)) {
982efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue            mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
983efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue            return false;
984efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue        }
985efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue
986efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue        String val = getRemoteDeviceProperty(address, "Trusted");
987efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue        if (val == null) {
988efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue            return false;
989efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue        } else {
990efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue            return val.equals("true") ? true : false;
991efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue        }
992efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue    }
993efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue
994efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue    /**
995d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh     * Gets the remote major, minor classes encoded as a 32-bit
9969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * integer.
9979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
9989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Note: this value is retrieved from cache, because we get it during
9999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *       remote-device discovery.
10009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
10019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return 32-bit integer encoding the remote major, minor, and service
10029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *         classes.
10039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
10049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public synchronized int getRemoteClass(String address) {
1005005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly        if (!BluetoothAdapter.checkBluetoothAddress(address)) {
1006ea600ccfb7568f60377c4abc85f56c80af7fdbfcNick Pelly            mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1007ea600ccfb7568f60377c4abc85f56c80af7fdbfcNick Pelly            return BluetoothClass.ERROR;
10089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1009d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        String val = getRemoteDeviceProperty(address, "Class");
1010d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        if (val == null)
1011d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh            return BluetoothClass.ERROR;
1012d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        else {
1013d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh            return Integer.valueOf(val);
1014d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        }
10159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1016d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh
10179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1019dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh     * Gets the UUIDs supported by the remote device
10209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
1021dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh     * @return array of 128bit ParcelUuids
10229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1023dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh    public synchronized ParcelUuid[] getRemoteUuids(String address) {
10249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1025005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly        if (!BluetoothAdapter.checkBluetoothAddress(address)) {
10269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return null;
10279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10281caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh        return getUuidFromCache(address);
10291caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh    }
10301caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh
10311caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh    private ParcelUuid[] getUuidFromCache(String address) {
1032d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        String value = getRemoteDeviceProperty(address, "UUIDs");
1033dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh        if (value == null) return null;
1034dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh
1035dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh        String[] uuidStrings = null;
1036d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        // The UUIDs are stored as a "," separated string.
1037dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh        uuidStrings = value.split(",");
1038dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh        ParcelUuid[] uuids = new ParcelUuid[uuidStrings.length];
1039dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh
1040dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh        for (int i = 0; i < uuidStrings.length; i++) {
1041dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh            uuids[i] = ParcelUuid.fromString(uuidStrings[i]);
1042dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh        }
1043d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        return uuids;
10449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10461caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh    public synchronized boolean fetchRemoteUuidsWithSdp(String address) {
10471caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
10481caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh        if (!BluetoothAdapter.checkBluetoothAddress(address)) {
10491caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh            return false;
10501caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh        }
10511caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh
10521caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh        if (mUuidIntentTracker.contains(address)) {
10531caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh            // An SDP query for this address is already in progress
10541caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh            return true;
10551caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh        }
10561caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh
10571caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh        boolean ret;
10581caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh        if (getBondState(address) == BluetoothDevice.BOND_BONDED) {
10591caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh            String path = getObjectPathFromAddress(address);
10601caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh            if (path == null) return false;
10611caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh
10621caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh            // Use an empty string for the UUID pattern
10631caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh            ret = discoverServicesNative(path, "");
10641caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh        } else {
10651caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh            ret = createDeviceNative(address);
10661caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh        }
10671caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh
10681caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh        mUuidIntentTracker.add(address);
10691caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh
10701caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh        Message message = mHandler.obtainMessage(MESSAGE_UUID_INTENT);
10711caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh        message.obj = address;
10721caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh        mHandler.sendMessageDelayed(message, UUID_INTENT_DELAY);
10731caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh        return ret;
10741caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh    }
10751caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh
10769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1077d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh     * Gets the rfcomm channel associated with the UUID.
10789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
1079d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh     * @param address Address of the remote device
1080dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh     * @param uuid ParcelUuid of the service attribute
10819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
1082d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh     * @return rfcomm channel associated with the service attribute
108310eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh     *         -1 on error
10849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1085dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh    public int getRemoteServiceChannel(String address, ParcelUuid uuid) {
10869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1087005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly        if (!BluetoothAdapter.checkBluetoothAddress(address)) {
1088b24e11baac589fe16426f2d243b460ab84991c7bNick Pelly            return BluetoothDevice.ERROR;
10899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
109010eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh        // Check if we are recovering from a crash.
109110eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh        if (mDeviceProperties.isEmpty()) {
109210eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh            if (!updateRemoteDevicePropertiesCache(address))
109310eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh                return -1;
109410eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh        }
109510eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh
109610eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh        Map<ParcelUuid, Integer> value = mDeviceServiceChannelCache.get(address);
109710eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh        if (value != null && value.containsKey(uuid))
109810eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh            return value.get(uuid);
109910eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh        return -1;
11009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public synchronized boolean setPin(String address, byte[] pin) {
11039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
11049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                                "Need BLUETOOTH_ADMIN permission");
11059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (pin == null || pin.length <= 0 || pin.length > 16 ||
1106005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly            !BluetoothAdapter.checkBluetoothAddress(address)) {
11079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
11089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        address = address.toUpperCase();
11109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Integer data = mEventLoop.getPasskeyAgentRequestData().remove(address);
11119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (data == null) {
11129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Log.w(TAG, "setPin(" + address + ") called but no native data available, " +
11139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                  "ignoring. Maybe the PasskeyAgent Request was cancelled by the remote device" +
11149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                  " or by bluez.\n");
11159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
11169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // bluez API wants pin as a string
11189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        String pinString;
11199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
11209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pinString = new String(pin, "UTF8");
11219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (UnsupportedEncodingException uee) {
11229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Log.e(TAG, "UTF8 not supported?!?");
11239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
11249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return setPinNative(address, pinString, data.intValue());
11269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1128b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh    public synchronized boolean setPasskey(String address, int passkey) {
1129b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
1130b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh                                                "Need BLUETOOTH_ADMIN permission");
1131005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly        if (passkey < 0 || passkey > 999999 || !BluetoothAdapter.checkBluetoothAddress(address)) {
1132b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh            return false;
1133b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh        }
1134b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh        address = address.toUpperCase();
1135b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh        Integer data = mEventLoop.getPasskeyAgentRequestData().remove(address);
1136b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh        if (data == null) {
1137b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh            Log.w(TAG, "setPasskey(" + address + ") called but no native data available, " +
1138b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh                  "ignoring. Maybe the PasskeyAgent Request was cancelled by the remote device" +
1139b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh                  " or by bluez.\n");
1140b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh            return false;
1141b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh        }
1142b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh        return setPasskeyNative(address, passkey, data.intValue());
1143b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh    }
1144b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh
1145b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh    public synchronized boolean setPairingConfirmation(String address, boolean confirm) {
1146b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
1147b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh                                                "Need BLUETOOTH_ADMIN permission");
1148b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh        address = address.toUpperCase();
1149b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh        Integer data = mEventLoop.getPasskeyAgentRequestData().remove(address);
1150b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh        if (data == null) {
1151b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh            Log.w(TAG, "setPasskey(" + address + ") called but no native data available, " +
1152b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh                  "ignoring. Maybe the PasskeyAgent Request was cancelled by the remote device" +
1153b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh                  " or by bluez.\n");
1154b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh            return false;
1155b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh        }
1156b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh        return setPairingConfirmationNative(address, confirm, data.intValue());
1157b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh    }
1158b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh
1159b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh    public synchronized boolean cancelPairingUserInput(String address) {
11609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
11619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                                "Need BLUETOOTH_ADMIN permission");
1162005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly        if (!BluetoothAdapter.checkBluetoothAddress(address)) {
11639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
11649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1165005b228cdfb369d9b3b325884c0337ba5968bf8cNick Pelly        mBondState.setBondState(address, BluetoothDevice.BOND_NONE,
1166397d8f4f4829a45f4fe7a672cc395466bbc0f442Jaikumar Ganesh                BluetoothDevice.UNBOND_REASON_AUTH_CANCELED);
11679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        address = address.toUpperCase();
11689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Integer data = mEventLoop.getPasskeyAgentRequestData().remove(address);
11699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (data == null) {
1170b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh            Log.w(TAG, "cancelUserInputNative(" + address + ") called but no native data " +
1171b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh                "available, ignoring. Maybe the PasskeyAgent Request was already cancelled " +
1172b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh                "by the remote or by bluez.\n");
11739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
11749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1175b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh        return cancelPairingUserInputNative(address, data.intValue());
11769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
117810eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh    public void updateDeviceServiceChannelCache(String address) {
117910eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh        ParcelUuid[] deviceUuids = getRemoteUuids(address);
118010eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh        // We are storing the rfcomm channel numbers only for the uuids
118110eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh        // we are interested in.
118210eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh        int channel;
118310eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh        ParcelUuid[] interestedUuids = {BluetoothUuid.Handsfree,
118410eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh                                        BluetoothUuid.HSP,
118510eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh                                        BluetoothUuid.ObexObjectPush};
118610eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh
118710eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh        Map <ParcelUuid, Integer> value = new HashMap<ParcelUuid, Integer>();
118810eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh        for (ParcelUuid uuid: interestedUuids) {
118910eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh            if (BluetoothUuid.isUuidPresent(deviceUuids, uuid)) {
119010eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh                channel =
119110eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh                   getDeviceServiceChannelNative(getObjectPathFromAddress(address), uuid.toString(),
119210eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh                                                 0x0004);
119310eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh                value.put(uuid, channel);
119410eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh            }
119510eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh        }
119610eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh        mDeviceServiceChannelCache.put(address, value);
119710eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh    }
119810eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh
11999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
12009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
12019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void onReceive(Context context, Intent intent) {
12029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String action = intent.getAction();
12039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (action.equals(Intent.ACTION_AIRPLANE_MODE_CHANGED)) {
12049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ContentResolver resolver = context.getContentResolver();
12059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Query the airplane mode from Settings.System just to make sure that
12069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // some random app is not sending this intent and disabling bluetooth
12079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                boolean enabled = !isAirplaneModeOn();
12089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // If bluetooth is currently expected to be on, then enable or disable bluetooth
12099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (Settings.Secure.getInt(resolver, Settings.Secure.BLUETOOTH_ON, 0) > 0) {
12109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (enabled) {
1211105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                        enable(false);
12129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    } else {
12139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        disable(false);
12149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
12159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
12169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    };
12199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void registerForAirplaneMode() {
12219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        String airplaneModeRadios = Settings.System.getString(mContext.getContentResolver(),
12229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Settings.System.AIRPLANE_MODE_RADIOS);
12239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mIsAirplaneSensitive = airplaneModeRadios == null
12249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ? true : airplaneModeRadios.contains(Settings.System.RADIO_BLUETOOTH);
12259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mIsAirplaneSensitive) {
12269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mIntentFilter = new IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED);
12279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mContext.registerReceiver(mReceiver, mIntentFilter);
12289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /* Returns true if airplane mode is currently on */
12329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final boolean isAirplaneModeOn() {
12339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return Settings.System.getInt(mContext.getContentResolver(),
12349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Settings.System.AIRPLANE_MODE_ON, 0) == 1;
12359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12371caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh    /* Broadcast the Uuid intent */
12381caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh    /*package*/ synchronized void sendUuidIntent(String address) {
12396179965e85ec17b836084a4a3d7963d8a7a1e1ccJaikumar Ganesh        ParcelUuid[] uuid = getUuidFromCache(address);
12406179965e85ec17b836084a4a3d7963d8a7a1e1ccJaikumar Ganesh        Intent intent = new Intent(BluetoothDevice.ACTION_UUID);
12412d3b98d868cda30535505b2a2fba47aa1c9c052bJaikumar Ganesh        intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mAdapter.getRemoteDevice(address));
12426179965e85ec17b836084a4a3d7963d8a7a1e1ccJaikumar Ganesh        intent.putExtra(BluetoothDevice.EXTRA_UUID, uuid);
12436179965e85ec17b836084a4a3d7963d8a7a1e1ccJaikumar Ganesh        mContext.sendBroadcast(intent, BLUETOOTH_ADMIN_PERM);
12441caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh
12456179965e85ec17b836084a4a3d7963d8a7a1e1ccJaikumar Ganesh        if (mUuidIntentTracker.contains(address))
12461caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh            mUuidIntentTracker.remove(address);
12471caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh    }
12481caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh
12499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
12509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1251105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        pw.println("\nmIsAirplaneSensitive = " + mIsAirplaneSensitive + "\n");
1252105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
1253105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        switch(mBluetoothState) {
1254de893f550301a60274e87aa8168225e7a7a42184Nick Pelly        case BluetoothAdapter.STATE_OFF:
1255105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            pw.println("\nBluetooth OFF\n");
1256105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            return;
1257de893f550301a60274e87aa8168225e7a7a42184Nick Pelly        case BluetoothAdapter.STATE_TURNING_ON:
1258105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            pw.println("\nBluetooth TURNING ON\n");
1259105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            return;
1260de893f550301a60274e87aa8168225e7a7a42184Nick Pelly        case BluetoothAdapter.STATE_TURNING_OFF:
1261105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            pw.println("\nBluetooth TURNING OFF\n");
1262105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            return;
1263de893f550301a60274e87aa8168225e7a7a42184Nick Pelly        case BluetoothAdapter.STATE_ON:
1264105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            pw.println("\nBluetooth ON\n");
1265105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        }
1266105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
1267105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        pw.println("\nLocal address = " + getAddress());
1268105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        pw.println("\nLocal name = " + getName());
1269105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        pw.println("\nisDiscovering() = " + isDiscovering());
1270105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
1271105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        BluetoothHeadset headset = new BluetoothHeadset(mContext, null);
1272105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
1273105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        pw.println("\n--Known devices--");
1274bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly        for (String address : mDeviceProperties.keySet()) {
12751eada0d3d655d6396bf862da954d254856a1bc03Nick Pelly            int bondState = mBondState.getBondState(address);
1276105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            pw.printf("%s %10s (%d) %s\n", address,
12771eada0d3d655d6396bf862da954d254856a1bc03Nick Pelly                       toBondStateString(bondState),
1278105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                       mBondState.getAttempt(address),
1279105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                       getRemoteName(address));
12801eada0d3d655d6396bf862da954d254856a1bc03Nick Pelly            if (bondState == BluetoothDevice.BOND_BONDED) {
1281dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh                ParcelUuid[] uuids = getRemoteUuids(address);
12821eada0d3d655d6396bf862da954d254856a1bc03Nick Pelly                if (uuids == null) {
12831eada0d3d655d6396bf862da954d254856a1bc03Nick Pelly                    pw.printf("\tuuids = null\n");
12841eada0d3d655d6396bf862da954d254856a1bc03Nick Pelly                } else {
1285dd0463aef18d251c741bfc9dc7a2787443ef36f1Jaikumar Ganesh                    for (ParcelUuid uuid : uuids) {
1286b015e193b7304230749bbf1e0676628b8a38de77Nick Pelly                        pw.printf("\t" + uuid + "\n");
12871eada0d3d655d6396bf862da954d254856a1bc03Nick Pelly                    }
12881eada0d3d655d6396bf862da954d254856a1bc03Nick Pelly                }
12891eada0d3d655d6396bf862da954d254856a1bc03Nick Pelly            }
1290105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        }
1291105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
1292d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        String value = getProperty("Devices");
12931eada0d3d655d6396bf862da954d254856a1bc03Nick Pelly        String[] devicesObjectPath = null;
1294d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        if (value != null) {
1295d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh            devicesObjectPath = value.split(",");
1296d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        }
1297105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        pw.println("\n--ACL connected devices--");
1298d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        for (String device : devicesObjectPath) {
1299d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh            pw.println(getAddressFromObjectPath(device));
1300105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        }
1301105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
1302105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        // Rather not do this from here, but no-where else and I need this
1303105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        // dump
1304105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        pw.println("\n--Headset Service--");
1305105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        switch (headset.getState()) {
1306105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        case BluetoothHeadset.STATE_DISCONNECTED:
1307105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            pw.println("getState() = STATE_DISCONNECTED");
1308105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            break;
1309105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        case BluetoothHeadset.STATE_CONNECTING:
1310105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            pw.println("getState() = STATE_CONNECTING");
1311105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            break;
1312105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        case BluetoothHeadset.STATE_CONNECTED:
1313105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            pw.println("getState() = STATE_CONNECTED");
1314105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            break;
1315105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        case BluetoothHeadset.STATE_ERROR:
1316105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            pw.println("getState() = STATE_ERROR");
1317105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            break;
1318105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        }
1319bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly        pw.println("getCurrentHeadset() = " + headset.getCurrentHeadset());
13206c901db72dbaf57d8fdf26adae6721de14ecae22Nick Pelly        pw.println("getBatteryUsageHint() = " + headset.getBatteryUsageHint());
13216c901db72dbaf57d8fdf26adae6721de14ecae22Nick Pelly
1322105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        headset.close();
13239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
13249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1325d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh    /* package */ static int bluezStringToScanMode(boolean pairable, boolean discoverable) {
1326d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        if (pairable && discoverable)
1327bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly            return BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE;
1328d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        else if (pairable && !discoverable)
1329bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly            return BluetoothAdapter.SCAN_MODE_CONNECTABLE;
1330d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        else
1331bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly            return BluetoothAdapter.SCAN_MODE_NONE;
13329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
13339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /* package */ static String scanModeToBluezString(int mode) {
13359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        switch (mode) {
1336bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly        case BluetoothAdapter.SCAN_MODE_NONE:
13379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return "off";
1338bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly        case BluetoothAdapter.SCAN_MODE_CONNECTABLE:
13399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return "connectable";
1340bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly        case BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE:
13419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return "discoverable";
13429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return null;
13449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
13459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1346d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh    /*package*/ String getAddressFromObjectPath(String objectPath) {
1347d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        String adapterObjectPath = getProperty("ObjectPath");
1348d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        if (adapterObjectPath == null || objectPath == null) {
1349d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh            Log.e(TAG, "getAddressFromObjectPath: AdpaterObjectPath:" + adapterObjectPath +
1350d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh                    "  or deviceObjectPath:" + objectPath + " is null");
1351d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh            return null;
1352d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        }
1353d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        if (!objectPath.startsWith(adapterObjectPath)) {
1354d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh            Log.e(TAG, "getAddressFromObjectPath: AdpaterObjectPath:" + adapterObjectPath +
1355d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh                    "  is not a prefix of deviceObjectPath:" + objectPath +
1356d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh                    "bluetoothd crashed ?");
1357d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh            return null;
1358d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        }
1359d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        String address = objectPath.substring(adapterObjectPath.length());
1360d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        if (address != null) return address.replace('_', ':');
1361d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh
1362d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        Log.e(TAG, "getAddressFromObjectPath: Address being returned is null");
1363d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        return null;
1364d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh    }
1365d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh
1366d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh    /*package*/ String getObjectPathFromAddress(String address) {
1367d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        String path = getProperty("ObjectPath");
1368d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        if (path == null) {
1369d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh            Log.e(TAG, "Error: Object Path is null");
1370d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh            return null;
1371d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        }
1372d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        path = path + address.replace(":", "_");
1373d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh        return path;
1374d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh    }
1375d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh
13769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static void log(String msg) {
13779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Log.d(TAG, msg);
13789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1379d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh
1380d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh    private native static void classInitNative();
1381d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh    private native void initializeNativeDataNative();
1382d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh    private native boolean setupNativeDataNative();
1383d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh    private native boolean tearDownNativeDataNative();
1384d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh    private native void cleanupNativeDataNative();
1385d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh    private native String getAdapterPathNative();
1386d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh
1387d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh    private native int isEnabledNative();
1388d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh    private native int enableNative();
1389d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh    private native int disableNative();
1390d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh
1391d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh    private native Object[] getAdapterPropertiesNative();
1392d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh    private native Object[] getDevicePropertiesNative(String objectPath);
1393d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh    private native boolean setAdapterPropertyStringNative(String key, String value);
1394d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh    private native boolean setAdapterPropertyIntegerNative(String key, int value);
1395d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh    private native boolean setAdapterPropertyBooleanNative(String key, int value);
1396d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh
1397d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh    private native boolean startDiscoveryNative();
1398d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh    private native boolean stopDiscoveryNative();
1399d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh
1400d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh    private native boolean createPairedDeviceNative(String address, int timeout_ms);
1401d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh    private native boolean cancelDeviceCreationNative(String address);
1402d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh    private native boolean removeDeviceNative(String objectPath);
1403d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh    private native int getDeviceServiceChannelNative(String objectPath, String uuid,
1404d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh            int attributeId);
1405d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh
1406b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh    private native boolean cancelPairingUserInputNative(String address, int nativeData);
1407d5ac1ae36b4e096eb97984334f86d0c68abea2f7Jaikumar Ganesh    private native boolean setPinNative(String address, String pin, int nativeData);
1408b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh    private native boolean setPasskeyNative(String address, int passkey, int nativeData);
1409b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh    private native boolean setPairingConfirmationNative(String address, boolean confirm,
1410b0eca41de0bb6747d8648b134912782e45e4cbefJaikumar Ganesh            int nativeData);
1411efa1dd716da3372cc74a201d11de5e0ef1a9fe9aLixin Yue    private native boolean setDevicePropertyBooleanNative(String objectPath, String key, int value);
14121caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh    private native boolean createDeviceNative(String address);
14131caa6d111eff6814760ec156b14adc29aa3aae6cJaikumar Ganesh    private native boolean discoverServicesNative(String objectPath, String pattern);
141410eac971b3a6e5f34a420dd68ebfa796553ad2b9Jaikumar Ganesh
14159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1416