1436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby/* 2b5f144af8ecc1c2f2e45f8a7d936f4ab368fdd97Matthew Xie * Copyright (C) 2012 The Android Open Source Project 3436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby * 4436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby * Licensed under the Apache License, Version 2.0 (the "License"); 5436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby * you may not use this file except in compliance with the License. 6436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby * You may obtain a copy of the License at 7436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby * 8436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby * http://www.apache.org/licenses/LICENSE-2.0 9436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby * 10436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby * Unless required by applicable law or agreed to in writing, software 11436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby * distributed under the License is distributed on an "AS IS" BASIS, 12436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby * See the License for the specific language governing permissions and 14436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby * limitations under the License. 15436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby */ 16436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 17436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hambypackage com.android.settings.bluetooth; 18436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 19654a3ab77dac5acaf6e100c518ba322cc1edb3c0fredcimport android.bluetooth.BluetoothAdapter; 20436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hambyimport android.bluetooth.BluetoothClass; 21436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hambyimport android.bluetooth.BluetoothDevice; 22436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hambyimport android.bluetooth.BluetoothInputDevice; 23436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hambyimport android.bluetooth.BluetoothProfile; 24436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hambyimport android.content.Context; 25654a3ab77dac5acaf6e100c518ba322cc1edb3c0fredcimport android.util.Log; 26436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 27436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hambyimport com.android.settings.R; 28436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 29436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hambyimport java.util.List; 30436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 31436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby/** 32436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby * HidProfile handles Bluetooth HID profile. 33436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby */ 34436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hambyfinal class HidProfile implements LocalBluetoothProfile { 35654a3ab77dac5acaf6e100c518ba322cc1edb3c0fredc private static final String TAG = "HidProfile"; 36654a3ab77dac5acaf6e100c518ba322cc1edb3c0fredc private static boolean V = true; 37654a3ab77dac5acaf6e100c518ba322cc1edb3c0fredc 38436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby private BluetoothInputDevice mService; 39654a3ab77dac5acaf6e100c518ba322cc1edb3c0fredc private boolean mIsProfileReady; 40436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 41436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby static final String NAME = "HID"; 42436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 43436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby // Order of this profile in device profiles list 44436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby private static final int ORDINAL = 3; 45436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 46436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby // These callbacks run on the main thread. 47436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby private final class InputDeviceServiceListener 48436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby implements BluetoothProfile.ServiceListener { 49436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 50436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby public void onServiceConnected(int profile, BluetoothProfile proxy) { 51654a3ab77dac5acaf6e100c518ba322cc1edb3c0fredc if (V) Log.d(TAG,"Bluetooth service connected"); 52436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby mService = (BluetoothInputDevice) proxy; 53654a3ab77dac5acaf6e100c518ba322cc1edb3c0fredc mIsProfileReady=true; 54436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 55436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 56436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby public void onServiceDisconnected(int profile) { 57654a3ab77dac5acaf6e100c518ba322cc1edb3c0fredc if (V) Log.d(TAG,"Bluetooth service disconnected"); 58654a3ab77dac5acaf6e100c518ba322cc1edb3c0fredc mIsProfileReady=false; 59436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 60436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 61436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 62654a3ab77dac5acaf6e100c518ba322cc1edb3c0fredc public boolean isProfileReady() { 63654a3ab77dac5acaf6e100c518ba322cc1edb3c0fredc return mIsProfileReady; 64654a3ab77dac5acaf6e100c518ba322cc1edb3c0fredc } 65654a3ab77dac5acaf6e100c518ba322cc1edb3c0fredc 66436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby HidProfile(Context context, LocalBluetoothAdapter adapter) { 67436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby adapter.getProfileProxy(context, new InputDeviceServiceListener(), 68436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby BluetoothProfile.INPUT_DEVICE); 69436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 70436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 71436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby public boolean isConnectable() { 72436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return true; 73436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 74436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 75436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby public boolean isAutoConnectable() { 76436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return true; 77436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 78436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 79436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby public boolean connect(BluetoothDevice device) { 80afedeacd575d51edc4f741bd2c8f75dd4928f2b6fredc if (mService == null) return false; 81436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return mService.connect(device); 82436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 83436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 84436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby public boolean disconnect(BluetoothDevice device) { 85afedeacd575d51edc4f741bd2c8f75dd4928f2b6fredc if (mService == null) return false; 86436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return mService.disconnect(device); 87436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 88436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 89436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby public int getConnectionStatus(BluetoothDevice device) { 90afedeacd575d51edc4f741bd2c8f75dd4928f2b6fredc if (mService == null) { 91afedeacd575d51edc4f741bd2c8f75dd4928f2b6fredc return BluetoothProfile.STATE_DISCONNECTED; 92afedeacd575d51edc4f741bd2c8f75dd4928f2b6fredc } 93436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby List<BluetoothDevice> deviceList = mService.getConnectedDevices(); 94436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 95436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return !deviceList.isEmpty() && deviceList.get(0).equals(device) 96436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby ? mService.getConnectionState(device) 97436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby : BluetoothProfile.STATE_DISCONNECTED; 98436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 99436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 100436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby public boolean isPreferred(BluetoothDevice device) { 101afedeacd575d51edc4f741bd2c8f75dd4928f2b6fredc if (mService == null) return false; 102436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return mService.getPriority(device) > BluetoothProfile.PRIORITY_OFF; 103436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 104436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 105436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby public int getPreferred(BluetoothDevice device) { 106afedeacd575d51edc4f741bd2c8f75dd4928f2b6fredc if (mService == null) return BluetoothProfile.PRIORITY_OFF; 107436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return mService.getPriority(device); 108436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 109436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 110436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby public void setPreferred(BluetoothDevice device, boolean preferred) { 111afedeacd575d51edc4f741bd2c8f75dd4928f2b6fredc if (mService == null) return; 112436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (preferred) { 113436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (mService.getPriority(device) < BluetoothProfile.PRIORITY_ON) { 114436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby mService.setPriority(device, BluetoothProfile.PRIORITY_ON); 115436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 116436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } else { 117436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby mService.setPriority(device, BluetoothProfile.PRIORITY_OFF); 118436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 119436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 120436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 121436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby public String toString() { 122436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return NAME; 123436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 124436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 125436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby public int getOrdinal() { 126436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return ORDINAL; 127436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 128436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 12979be0b3e6b5639c4cbe2bbcd9adb0ec4c28716edJake Hamby public int getNameResource(BluetoothDevice device) { 13079be0b3e6b5639c4cbe2bbcd9adb0ec4c28716edJake Hamby // TODO: distinguish between keyboard and mouse? 131436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return R.string.bluetooth_profile_hid; 132436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 133436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 134436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby public int getSummaryResourceForDevice(BluetoothDevice device) { 135afedeacd575d51edc4f741bd2c8f75dd4928f2b6fredc int state = getConnectionStatus(device); 136436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby switch (state) { 137436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby case BluetoothProfile.STATE_DISCONNECTED: 138436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return R.string.bluetooth_hid_profile_summary_use_for; 139436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 140436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby case BluetoothProfile.STATE_CONNECTED: 141436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return R.string.bluetooth_hid_profile_summary_connected; 142436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 143436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby default: 144436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return Utils.getConnectionStateSummary(state); 145436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 146436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 147436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 148436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby public int getDrawableResource(BluetoothClass btClass) { 149436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby if (btClass == null) { 150436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return R.drawable.ic_bt_keyboard_hid; 151436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 152436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return getHidClassDrawable(btClass); 153436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 154436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby 155436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby static int getHidClassDrawable(BluetoothClass btClass) { 156436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby switch (btClass.getDeviceClass()) { 157436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby case BluetoothClass.Device.PERIPHERAL_KEYBOARD: 158436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby case BluetoothClass.Device.PERIPHERAL_KEYBOARD_POINTING: 159436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return R.drawable.ic_bt_keyboard_hid; 160436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby case BluetoothClass.Device.PERIPHERAL_POINTING: 161436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return R.drawable.ic_bt_pointing_hid; 162436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby default: 163436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby return R.drawable.ic_bt_misc_hid; 164436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 165436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } 166654a3ab77dac5acaf6e100c518ba322cc1edb3c0fredc 167654a3ab77dac5acaf6e100c518ba322cc1edb3c0fredc protected void finalize() { 168654a3ab77dac5acaf6e100c518ba322cc1edb3c0fredc if (V) Log.d(TAG, "finalize()"); 169654a3ab77dac5acaf6e100c518ba322cc1edb3c0fredc if (mService != null) { 170654a3ab77dac5acaf6e100c518ba322cc1edb3c0fredc try { 171b5f144af8ecc1c2f2e45f8a7d936f4ab368fdd97Matthew Xie BluetoothAdapter.getDefaultAdapter().closeProfileProxy(BluetoothProfile.INPUT_DEVICE, 172b5f144af8ecc1c2f2e45f8a7d936f4ab368fdd97Matthew Xie mService); 173654a3ab77dac5acaf6e100c518ba322cc1edb3c0fredc mService = null; 174654a3ab77dac5acaf6e100c518ba322cc1edb3c0fredc }catch (Throwable t) { 175654a3ab77dac5acaf6e100c518ba322cc1edb3c0fredc Log.w(TAG, "Error cleaning up HID proxy", t); 176654a3ab77dac5acaf6e100c518ba322cc1edb3c0fredc } 177654a3ab77dac5acaf6e100c518ba322cc1edb3c0fredc } 178654a3ab77dac5acaf6e100c518ba322cc1edb3c0fredc } 179436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby} 180