Home | History | Annotate | Download | only in bluetooth
      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 
     17 package com.android.settingslib.bluetooth;
     18 
     19 import android.bluetooth.BluetoothAdapter;
     20 import android.bluetooth.BluetoothClass;
     21 import android.bluetooth.BluetoothDevice;
     22 import android.bluetooth.BluetoothInputDevice;
     23 import android.bluetooth.BluetoothProfile;
     24 import android.content.Context;
     25 import android.util.Log;
     26 
     27 import com.android.settingslib.R;
     28 
     29 import java.util.List;
     30 
     31 /**
     32  * HidProfile handles Bluetooth HID profile.
     33  */
     34 public 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     private final LocalBluetoothAdapter mLocalAdapter;
     42     private final CachedBluetoothDeviceManager mDeviceManager;
     43     private final LocalBluetoothProfileManager mProfileManager;
     44 
     45     static final String NAME = "HID";
     46 
     47     // Order of this profile in device profiles list
     48     private static final int ORDINAL = 3;
     49 
     50     // These callbacks run on the main thread.
     51     private final class InputDeviceServiceListener
     52             implements BluetoothProfile.ServiceListener {
     53 
     54         public void onServiceConnected(int profile, BluetoothProfile proxy) {
     55             if (V) Log.d(TAG,"Bluetooth service connected");
     56             mService = (BluetoothInputDevice) proxy;
     57             // We just bound to the service, so refresh the UI for any connected HID devices.
     58             List<BluetoothDevice> deviceList = mService.getConnectedDevices();
     59             while (!deviceList.isEmpty()) {
     60                 BluetoothDevice nextDevice = deviceList.remove(0);
     61                 CachedBluetoothDevice device = mDeviceManager.findDevice(nextDevice);
     62                 // we may add a new device here, but generally this should not happen
     63                 if (device == null) {
     64                     Log.w(TAG, "HidProfile found new device: " + nextDevice);
     65                     device = mDeviceManager.addDevice(mLocalAdapter, mProfileManager, nextDevice);
     66                 }
     67                 device.onProfileStateChanged(HidProfile.this, BluetoothProfile.STATE_CONNECTED);
     68                 device.refresh();
     69             }
     70             mIsProfileReady=true;
     71         }
     72 
     73         public void onServiceDisconnected(int profile) {
     74             if (V) Log.d(TAG,"Bluetooth service disconnected");
     75             mIsProfileReady=false;
     76         }
     77     }
     78 
     79     public boolean isProfileReady() {
     80         return mIsProfileReady;
     81     }
     82 
     83     HidProfile(Context context, LocalBluetoothAdapter adapter,
     84         CachedBluetoothDeviceManager deviceManager,
     85         LocalBluetoothProfileManager profileManager) {
     86         mLocalAdapter = adapter;
     87         mDeviceManager = deviceManager;
     88         mProfileManager = profileManager;
     89         adapter.getProfileProxy(context, new InputDeviceServiceListener(),
     90                 BluetoothProfile.INPUT_DEVICE);
     91     }
     92 
     93     public boolean isConnectable() {
     94         return true;
     95     }
     96 
     97     public boolean isAutoConnectable() {
     98         return true;
     99     }
    100 
    101     public boolean connect(BluetoothDevice device) {
    102         if (mService == null) return false;
    103         return mService.connect(device);
    104     }
    105 
    106     public boolean disconnect(BluetoothDevice device) {
    107         if (mService == null) return false;
    108         return mService.disconnect(device);
    109     }
    110 
    111     public int getConnectionStatus(BluetoothDevice device) {
    112         if (mService == null) {
    113             return BluetoothProfile.STATE_DISCONNECTED;
    114         }
    115         List<BluetoothDevice> deviceList = mService.getConnectedDevices();
    116 
    117         return !deviceList.isEmpty() && deviceList.get(0).equals(device)
    118                 ? mService.getConnectionState(device)
    119                 : BluetoothProfile.STATE_DISCONNECTED;
    120     }
    121 
    122     public boolean isPreferred(BluetoothDevice device) {
    123         if (mService == null) return false;
    124         return mService.getPriority(device) > BluetoothProfile.PRIORITY_OFF;
    125     }
    126 
    127     public int getPreferred(BluetoothDevice device) {
    128         if (mService == null) return BluetoothProfile.PRIORITY_OFF;
    129         return mService.getPriority(device);
    130     }
    131 
    132     public void setPreferred(BluetoothDevice device, boolean preferred) {
    133         if (mService == null) return;
    134         if (preferred) {
    135             if (mService.getPriority(device) < BluetoothProfile.PRIORITY_ON) {
    136                 mService.setPriority(device, BluetoothProfile.PRIORITY_ON);
    137             }
    138         } else {
    139             mService.setPriority(device, BluetoothProfile.PRIORITY_OFF);
    140         }
    141     }
    142 
    143     public String toString() {
    144         return NAME;
    145     }
    146 
    147     public int getOrdinal() {
    148         return ORDINAL;
    149     }
    150 
    151     public int getNameResource(BluetoothDevice device) {
    152         // TODO: distinguish between keyboard and mouse?
    153         return R.string.bluetooth_profile_hid;
    154     }
    155 
    156     public int getSummaryResourceForDevice(BluetoothDevice device) {
    157         int state = getConnectionStatus(device);
    158         switch (state) {
    159             case BluetoothProfile.STATE_DISCONNECTED:
    160                 return R.string.bluetooth_hid_profile_summary_use_for;
    161 
    162             case BluetoothProfile.STATE_CONNECTED:
    163                 return R.string.bluetooth_hid_profile_summary_connected;
    164 
    165             default:
    166                 return Utils.getConnectionStateSummary(state);
    167         }
    168     }
    169 
    170     public int getDrawableResource(BluetoothClass btClass) {
    171         if (btClass == null) {
    172             return R.drawable.ic_lockscreen_ime;
    173         }
    174         return getHidClassDrawable(btClass);
    175     }
    176 
    177     public static int getHidClassDrawable(BluetoothClass btClass) {
    178         switch (btClass.getDeviceClass()) {
    179             case BluetoothClass.Device.PERIPHERAL_KEYBOARD:
    180             case BluetoothClass.Device.PERIPHERAL_KEYBOARD_POINTING:
    181                 return R.drawable.ic_lockscreen_ime;
    182             case BluetoothClass.Device.PERIPHERAL_POINTING:
    183                 return R.drawable.ic_bt_pointing_hid;
    184             default:
    185                 return R.drawable.ic_bt_misc_hid;
    186         }
    187     }
    188 
    189     protected void finalize() {
    190         if (V) Log.d(TAG, "finalize()");
    191         if (mService != null) {
    192             try {
    193                 BluetoothAdapter.getDefaultAdapter().closeProfileProxy(BluetoothProfile.INPUT_DEVICE,
    194                                                                        mService);
    195                 mService = null;
    196             }catch (Throwable t) {
    197                 Log.w(TAG, "Error cleaning up HID proxy", t);
    198             }
    199         }
    200     }
    201 }
    202