1/* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.settings.bluetooth; 18 19import android.bluetooth.BluetoothAdapter; 20import android.bluetooth.BluetoothClass; 21import android.bluetooth.BluetoothDevice; 22import android.bluetooth.BluetoothInputDevice; 23import android.bluetooth.BluetoothProfile; 24import android.content.Context; 25import android.util.Log; 26 27import com.android.settings.R; 28 29import java.util.List; 30 31/** 32 * HidProfile handles Bluetooth HID profile. 33 */ 34final class HidProfile implements LocalBluetoothProfile { 35 private static final String TAG = "HidProfile"; 36 private static boolean V = true; 37 38 private BluetoothInputDevice mService; 39 private boolean mIsProfileReady; 40 41 static final String NAME = "HID"; 42 43 // Order of this profile in device profiles list 44 private static final int ORDINAL = 3; 45 46 // These callbacks run on the main thread. 47 private final class InputDeviceServiceListener 48 implements BluetoothProfile.ServiceListener { 49 50 public void onServiceConnected(int profile, BluetoothProfile proxy) { 51 if (V) Log.d(TAG,"Bluetooth service connected"); 52 mService = (BluetoothInputDevice) proxy; 53 mIsProfileReady=true; 54 } 55 56 public void onServiceDisconnected(int profile) { 57 if (V) Log.d(TAG,"Bluetooth service disconnected"); 58 mIsProfileReady=false; 59 } 60 } 61 62 public boolean isProfileReady() { 63 return mIsProfileReady; 64 } 65 66 HidProfile(Context context, LocalBluetoothAdapter adapter) { 67 adapter.getProfileProxy(context, new InputDeviceServiceListener(), 68 BluetoothProfile.INPUT_DEVICE); 69 } 70 71 public boolean isConnectable() { 72 return true; 73 } 74 75 public boolean isAutoConnectable() { 76 return true; 77 } 78 79 public boolean connect(BluetoothDevice device) { 80 if (mService == null) return false; 81 return mService.connect(device); 82 } 83 84 public boolean disconnect(BluetoothDevice device) { 85 if (mService == null) return false; 86 return mService.disconnect(device); 87 } 88 89 public int getConnectionStatus(BluetoothDevice device) { 90 if (mService == null) { 91 return BluetoothProfile.STATE_DISCONNECTED; 92 } 93 List<BluetoothDevice> deviceList = mService.getConnectedDevices(); 94 95 return !deviceList.isEmpty() && deviceList.get(0).equals(device) 96 ? mService.getConnectionState(device) 97 : BluetoothProfile.STATE_DISCONNECTED; 98 } 99 100 public boolean isPreferred(BluetoothDevice device) { 101 if (mService == null) return false; 102 return mService.getPriority(device) > BluetoothProfile.PRIORITY_OFF; 103 } 104 105 public int getPreferred(BluetoothDevice device) { 106 if (mService == null) return BluetoothProfile.PRIORITY_OFF; 107 return mService.getPriority(device); 108 } 109 110 public void setPreferred(BluetoothDevice device, boolean preferred) { 111 if (mService == null) return; 112 if (preferred) { 113 if (mService.getPriority(device) < BluetoothProfile.PRIORITY_ON) { 114 mService.setPriority(device, BluetoothProfile.PRIORITY_ON); 115 } 116 } else { 117 mService.setPriority(device, BluetoothProfile.PRIORITY_OFF); 118 } 119 } 120 121 public String toString() { 122 return NAME; 123 } 124 125 public int getOrdinal() { 126 return ORDINAL; 127 } 128 129 public int getNameResource(BluetoothDevice device) { 130 // TODO: distinguish between keyboard and mouse? 131 return R.string.bluetooth_profile_hid; 132 } 133 134 public int getSummaryResourceForDevice(BluetoothDevice device) { 135 int state = getConnectionStatus(device); 136 switch (state) { 137 case BluetoothProfile.STATE_DISCONNECTED: 138 return R.string.bluetooth_hid_profile_summary_use_for; 139 140 case BluetoothProfile.STATE_CONNECTED: 141 return R.string.bluetooth_hid_profile_summary_connected; 142 143 default: 144 return Utils.getConnectionStateSummary(state); 145 } 146 } 147 148 public int getDrawableResource(BluetoothClass btClass) { 149 if (btClass == null) { 150 return R.drawable.ic_bt_keyboard_hid; 151 } 152 return getHidClassDrawable(btClass); 153 } 154 155 static int getHidClassDrawable(BluetoothClass btClass) { 156 switch (btClass.getDeviceClass()) { 157 case BluetoothClass.Device.PERIPHERAL_KEYBOARD: 158 case BluetoothClass.Device.PERIPHERAL_KEYBOARD_POINTING: 159 return R.drawable.ic_bt_keyboard_hid; 160 case BluetoothClass.Device.PERIPHERAL_POINTING: 161 return R.drawable.ic_bt_pointing_hid; 162 default: 163 return R.drawable.ic_bt_misc_hid; 164 } 165 } 166 167 protected void finalize() { 168 if (V) Log.d(TAG, "finalize()"); 169 if (mService != null) { 170 try { 171 BluetoothAdapter.getDefaultAdapter().closeProfileProxy(BluetoothProfile.INPUT_DEVICE, 172 mService); 173 mService = null; 174 }catch (Throwable t) { 175 Log.w(TAG, "Error cleaning up HID proxy", t); 176 } 177 } 178 } 179} 180