1545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh/*
24ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh * Copyright (C) 2011 The Android Open Source Project
3545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh *
4545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh * Licensed under the Apache License, Version 2.0 (the "License");
5545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh * you may not use this file except in compliance with the License.
6545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh * You may obtain a copy of the License at
7545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh *
8545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh *      http://www.apache.org/licenses/LICENSE-2.0
9545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh *
10545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh * Unless required by applicable law or agreed to in writing, software
11545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh * distributed under the License is distributed on an "AS IS" BASIS,
12545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh * See the License for the specific language governing permissions and
14545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh * limitations under the License.
15545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh */
16545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh
17545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganeshpackage android.bluetooth;
18545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh
19545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganeshimport android.annotation.SdkConstant;
20545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganeshimport android.annotation.SdkConstant.SdkConstantType;
21bf246ef0abb6ea354fe412b139dec1adb4e5791dMatthew Xieimport android.content.ComponentName;
22545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganeshimport android.content.Context;
23bf246ef0abb6ea354fe412b139dec1adb4e5791dMatthew Xieimport android.content.Intent;
24bf246ef0abb6ea354fe412b139dec1adb4e5791dMatthew Xieimport android.content.ServiceConnection;
25545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganeshimport android.os.IBinder;
26545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganeshimport android.os.RemoteException;
27349e62f329bbb8edab89356973773a5648f26751Priti Agheraimport android.os.ServiceManager;
28545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganeshimport android.util.Log;
29545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh
305a1e4cf83f5be1b5d79e2643fa791aa269b6a4bcJaikumar Ganeshimport java.util.ArrayList;
315a1e4cf83f5be1b5d79e2643fa791aa269b6a4bcJaikumar Ganeshimport java.util.List;
32545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh
334ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh
34545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh/**
354ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh * This class provides the public APIs to control the Bluetooth Input
364ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh * Device Profile.
37545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh *
384ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh *<p>BluetoothInputDevice is a proxy object for controlling the Bluetooth
394ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh * Service via IPC. Use {@link BluetoothAdapter#getProfileProxy} to get
404ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh * the BluetoothInputDevice proxy object.
41545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh *
424ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh *<p>Each method is protected with its appropriate permission.
434ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh *@hide
44545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh */
454ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganeshpublic final class BluetoothInputDevice implements BluetoothProfile {
46545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh    private static final String TAG = "BluetoothInputDevice";
470f42037eb7b5118015c2caca635538324ccf0ccffredc    private static final boolean DBG = true;
48563e414784eb81e4ea4051667d5c8855b17f7534Matthew Xie    private static final boolean VDBG = false;
49545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh
50545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh    /**
514ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh     * Intent used to broadcast the change in connection state of the Input
524ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh     * Device profile.
534ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh     *
544ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh     * <p>This intent will have 3 extras:
554ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh     * <ul>
564ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh     *   <li> {@link #EXTRA_STATE} - The current state of the profile. </li>
574ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh     *   <li> {@link #EXTRA_PREVIOUS_STATE}- The previous state of the profile.</li>
584ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh     *   <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li>
594ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh     * </ul>
604ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh     *
614ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh     * <p>{@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} can be any of
624ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh     * {@link #STATE_DISCONNECTED}, {@link #STATE_CONNECTING},
634ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh     * {@link #STATE_CONNECTED}, {@link #STATE_DISCONNECTING}.
644ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh     *
654ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission to
664ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh     * receive.
67545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh     */
684ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
694ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh    public static final String ACTION_CONNECTION_STATE_CHANGED =
704ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh        "android.bluetooth.input.profile.action.CONNECTION_STATE_CHANGED";
71545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh
72fbe807d064ada99211b102914df514aa562256f8Jaikumar Ganesh    /**
73349e62f329bbb8edab89356973773a5648f26751Priti Aghera     * @hide
74349e62f329bbb8edab89356973773a5648f26751Priti Aghera     */
75349e62f329bbb8edab89356973773a5648f26751Priti Aghera    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
76349e62f329bbb8edab89356973773a5648f26751Priti Aghera    public static final String ACTION_PROTOCOL_MODE_CHANGED =
77349e62f329bbb8edab89356973773a5648f26751Priti Aghera        "android.bluetooth.input.profile.action.PROTOCOL_MODE_CHANGED";
78349e62f329bbb8edab89356973773a5648f26751Priti Aghera
79349e62f329bbb8edab89356973773a5648f26751Priti Aghera
80349e62f329bbb8edab89356973773a5648f26751Priti Aghera    /**
81349e62f329bbb8edab89356973773a5648f26751Priti Aghera     * @hide
82349e62f329bbb8edab89356973773a5648f26751Priti Aghera     */
83349e62f329bbb8edab89356973773a5648f26751Priti Aghera    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
84349e62f329bbb8edab89356973773a5648f26751Priti Aghera    public static final String ACTION_VIRTUAL_UNPLUG_STATUS =
85349e62f329bbb8edab89356973773a5648f26751Priti Aghera        "android.bluetooth.input.profile.action.VIRTUAL_UNPLUG_STATUS";
86349e62f329bbb8edab89356973773a5648f26751Priti Aghera
87349e62f329bbb8edab89356973773a5648f26751Priti Aghera
88349e62f329bbb8edab89356973773a5648f26751Priti Aghera    /**
89fbe807d064ada99211b102914df514aa562256f8Jaikumar Ganesh     * Return codes for the connect and disconnect Bluez / Dbus calls.
904ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh     * @hide
91fbe807d064ada99211b102914df514aa562256f8Jaikumar Ganesh     */
92fbe807d064ada99211b102914df514aa562256f8Jaikumar Ganesh    public static final int INPUT_DISCONNECT_FAILED_NOT_CONNECTED = 5000;
93fbe807d064ada99211b102914df514aa562256f8Jaikumar Ganesh
944ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh    /**
954ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh     * @hide
964ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh     */
97fbe807d064ada99211b102914df514aa562256f8Jaikumar Ganesh    public static final int INPUT_CONNECT_FAILED_ALREADY_CONNECTED = 5001;
98fbe807d064ada99211b102914df514aa562256f8Jaikumar Ganesh
994ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh    /**
1004ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh     * @hide
1014ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh     */
102fbe807d064ada99211b102914df514aa562256f8Jaikumar Ganesh    public static final int INPUT_CONNECT_FAILED_ATTEMPT_FAILED = 5002;
103fbe807d064ada99211b102914df514aa562256f8Jaikumar Ganesh
1044ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh    /**
1054ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh     * @hide
1064ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh     */
107fbe807d064ada99211b102914df514aa562256f8Jaikumar Ganesh    public static final int INPUT_OPERATION_GENERIC_FAILURE = 5003;
108fbe807d064ada99211b102914df514aa562256f8Jaikumar Ganesh
1094ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh    /**
1104ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh     * @hide
1114ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh     */
112fbe807d064ada99211b102914df514aa562256f8Jaikumar Ganesh    public static final int INPUT_OPERATION_SUCCESS = 5004;
113fbe807d064ada99211b102914df514aa562256f8Jaikumar Ganesh
114349e62f329bbb8edab89356973773a5648f26751Priti Aghera    /**
115349e62f329bbb8edab89356973773a5648f26751Priti Aghera     * @hide
116349e62f329bbb8edab89356973773a5648f26751Priti Aghera     */
117349e62f329bbb8edab89356973773a5648f26751Priti Aghera    public static final int PROTOCOL_REPORT_MODE = 0;
118349e62f329bbb8edab89356973773a5648f26751Priti Aghera
119349e62f329bbb8edab89356973773a5648f26751Priti Aghera    /**
120349e62f329bbb8edab89356973773a5648f26751Priti Aghera     * @hide
121349e62f329bbb8edab89356973773a5648f26751Priti Aghera     */
122349e62f329bbb8edab89356973773a5648f26751Priti Aghera    public static final int PROTOCOL_BOOT_MODE = 1;
123349e62f329bbb8edab89356973773a5648f26751Priti Aghera
124349e62f329bbb8edab89356973773a5648f26751Priti Aghera    /**
125349e62f329bbb8edab89356973773a5648f26751Priti Aghera     * @hide
126349e62f329bbb8edab89356973773a5648f26751Priti Aghera     */
127349e62f329bbb8edab89356973773a5648f26751Priti Aghera    public static final int PROTOCOL_UNSUPPORTED_MODE = 255;
128349e62f329bbb8edab89356973773a5648f26751Priti Aghera
129349e62f329bbb8edab89356973773a5648f26751Priti Aghera    /*  int reportType, int reportType, int bufferSize */
130349e62f329bbb8edab89356973773a5648f26751Priti Aghera    /**
131349e62f329bbb8edab89356973773a5648f26751Priti Aghera     * @hide
132349e62f329bbb8edab89356973773a5648f26751Priti Aghera     */
133349e62f329bbb8edab89356973773a5648f26751Priti Aghera    public static final byte REPORT_TYPE_INPUT = 0;
134349e62f329bbb8edab89356973773a5648f26751Priti Aghera
135349e62f329bbb8edab89356973773a5648f26751Priti Aghera    /**
136349e62f329bbb8edab89356973773a5648f26751Priti Aghera     * @hide
137349e62f329bbb8edab89356973773a5648f26751Priti Aghera     */
138349e62f329bbb8edab89356973773a5648f26751Priti Aghera    public static final byte REPORT_TYPE_OUTPUT = 1;
139349e62f329bbb8edab89356973773a5648f26751Priti Aghera
140349e62f329bbb8edab89356973773a5648f26751Priti Aghera    /**
141349e62f329bbb8edab89356973773a5648f26751Priti Aghera     * @hide
142349e62f329bbb8edab89356973773a5648f26751Priti Aghera     */
143349e62f329bbb8edab89356973773a5648f26751Priti Aghera    public static final byte REPORT_TYPE_FEATURE = 2;
144349e62f329bbb8edab89356973773a5648f26751Priti Aghera
145349e62f329bbb8edab89356973773a5648f26751Priti Aghera    /**
146349e62f329bbb8edab89356973773a5648f26751Priti Aghera     * @hide
147349e62f329bbb8edab89356973773a5648f26751Priti Aghera     */
148349e62f329bbb8edab89356973773a5648f26751Priti Aghera    public static final int VIRTUAL_UNPLUG_STATUS_SUCCESS = 0;
149349e62f329bbb8edab89356973773a5648f26751Priti Aghera
150349e62f329bbb8edab89356973773a5648f26751Priti Aghera    /**
151349e62f329bbb8edab89356973773a5648f26751Priti Aghera     * @hide
152349e62f329bbb8edab89356973773a5648f26751Priti Aghera     */
153349e62f329bbb8edab89356973773a5648f26751Priti Aghera    public static final int VIRTUAL_UNPLUG_STATUS_FAIL = 1;
154349e62f329bbb8edab89356973773a5648f26751Priti Aghera
155349e62f329bbb8edab89356973773a5648f26751Priti Aghera    /**
156349e62f329bbb8edab89356973773a5648f26751Priti Aghera     * @hide
157349e62f329bbb8edab89356973773a5648f26751Priti Aghera     */
158349e62f329bbb8edab89356973773a5648f26751Priti Aghera    public static final String EXTRA_PROTOCOL_MODE = "android.bluetooth.BluetoothInputDevice.extra.PROTOCOL_MODE";
159349e62f329bbb8edab89356973773a5648f26751Priti Aghera
160349e62f329bbb8edab89356973773a5648f26751Priti Aghera    /**
161349e62f329bbb8edab89356973773a5648f26751Priti Aghera     * @hide
162349e62f329bbb8edab89356973773a5648f26751Priti Aghera     */
163349e62f329bbb8edab89356973773a5648f26751Priti Aghera    public static final String EXTRA_REPORT_TYPE = "android.bluetooth.BluetoothInputDevice.extra.REPORT_TYPE";
164349e62f329bbb8edab89356973773a5648f26751Priti Aghera
165349e62f329bbb8edab89356973773a5648f26751Priti Aghera    /**
166349e62f329bbb8edab89356973773a5648f26751Priti Aghera     * @hide
167349e62f329bbb8edab89356973773a5648f26751Priti Aghera     */
168349e62f329bbb8edab89356973773a5648f26751Priti Aghera    public static final String EXTRA_REPORT_ID = "android.bluetooth.BluetoothInputDevice.extra.REPORT_ID";
169349e62f329bbb8edab89356973773a5648f26751Priti Aghera
170349e62f329bbb8edab89356973773a5648f26751Priti Aghera    /**
171349e62f329bbb8edab89356973773a5648f26751Priti Aghera     * @hide
172349e62f329bbb8edab89356973773a5648f26751Priti Aghera     */
173349e62f329bbb8edab89356973773a5648f26751Priti Aghera    public static final String EXTRA_REPORT_BUFFER_SIZE = "android.bluetooth.BluetoothInputDevice.extra.REPORT_BUFFER_SIZE";
174349e62f329bbb8edab89356973773a5648f26751Priti Aghera
175349e62f329bbb8edab89356973773a5648f26751Priti Aghera    /**
176349e62f329bbb8edab89356973773a5648f26751Priti Aghera     * @hide
177349e62f329bbb8edab89356973773a5648f26751Priti Aghera     */
178349e62f329bbb8edab89356973773a5648f26751Priti Aghera    public static final String EXTRA_REPORT = "android.bluetooth.BluetoothInputDevice.extra.REPORT";
179349e62f329bbb8edab89356973773a5648f26751Priti Aghera
180349e62f329bbb8edab89356973773a5648f26751Priti Aghera    /**
181349e62f329bbb8edab89356973773a5648f26751Priti Aghera     * @hide
182349e62f329bbb8edab89356973773a5648f26751Priti Aghera     */
183349e62f329bbb8edab89356973773a5648f26751Priti Aghera    public static final String EXTRA_VIRTUAL_UNPLUG_STATUS = "android.bluetooth.BluetoothInputDevice.extra.VIRTUAL_UNPLUG_STATUS";
184349e62f329bbb8edab89356973773a5648f26751Priti Aghera
185bf246ef0abb6ea354fe412b139dec1adb4e5791dMatthew Xie    private Context mContext;
1864ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh    private ServiceListener mServiceListener;
1874ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh    private BluetoothAdapter mAdapter;
188bf246ef0abb6ea354fe412b139dec1adb4e5791dMatthew Xie    private IBluetoothInputDevice mService;
189545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh
1900f42037eb7b5118015c2caca635538324ccf0ccffredc    final private IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
1910f42037eb7b5118015c2caca635538324ccf0ccffredc            new IBluetoothStateChangeCallback.Stub() {
1920f42037eb7b5118015c2caca635538324ccf0ccffredc                public void onBluetoothStateChange(boolean up) {
1930f42037eb7b5118015c2caca635538324ccf0ccffredc                    if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up);
1940f42037eb7b5118015c2caca635538324ccf0ccffredc                    if (!up) {
195563e414784eb81e4ea4051667d5c8855b17f7534Matthew Xie                        if (VDBG) Log.d(TAG,"Unbinding service...");
1960f42037eb7b5118015c2caca635538324ccf0ccffredc                        synchronized (mConnection) {
1970f42037eb7b5118015c2caca635538324ccf0ccffredc                            try {
1980f42037eb7b5118015c2caca635538324ccf0ccffredc                                mService = null;
1990f42037eb7b5118015c2caca635538324ccf0ccffredc                                mContext.unbindService(mConnection);
2000f42037eb7b5118015c2caca635538324ccf0ccffredc                            } catch (Exception re) {
2010f42037eb7b5118015c2caca635538324ccf0ccffredc                                Log.e(TAG,"",re);
2020f42037eb7b5118015c2caca635538324ccf0ccffredc                            }
2030f42037eb7b5118015c2caca635538324ccf0ccffredc                        }
2040f42037eb7b5118015c2caca635538324ccf0ccffredc                    } else {
2050f42037eb7b5118015c2caca635538324ccf0ccffredc                        synchronized (mConnection) {
2060f42037eb7b5118015c2caca635538324ccf0ccffredc                            try {
2070f42037eb7b5118015c2caca635538324ccf0ccffredc                                if (mService == null) {
208563e414784eb81e4ea4051667d5c8855b17f7534Matthew Xie                                    if (VDBG) Log.d(TAG,"Binding service...");
2090f42037eb7b5118015c2caca635538324ccf0ccffredc                                    if (!mContext.bindService(new Intent(IBluetoothInputDevice.class.getName()), mConnection, 0)) {
2100f42037eb7b5118015c2caca635538324ccf0ccffredc                                        Log.e(TAG, "Could not bind to Bluetooth HID Service");
2110f42037eb7b5118015c2caca635538324ccf0ccffredc                                    }
2120f42037eb7b5118015c2caca635538324ccf0ccffredc                                }
2130f42037eb7b5118015c2caca635538324ccf0ccffredc                            } catch (Exception re) {
2140f42037eb7b5118015c2caca635538324ccf0ccffredc                                Log.e(TAG,"",re);
2150f42037eb7b5118015c2caca635538324ccf0ccffredc                            }
2160f42037eb7b5118015c2caca635538324ccf0ccffredc                        }
2170f42037eb7b5118015c2caca635538324ccf0ccffredc                    }
2180f42037eb7b5118015c2caca635538324ccf0ccffredc                }
2190f42037eb7b5118015c2caca635538324ccf0ccffredc        };
2200f42037eb7b5118015c2caca635538324ccf0ccffredc
221545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh    /**
222545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh     * Create a BluetoothInputDevice proxy object for interacting with the local
2234ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh     * Bluetooth Service which handles the InputDevice profile
2244ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh     *
225545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh     */
226bf246ef0abb6ea354fe412b139dec1adb4e5791dMatthew Xie    /*package*/ BluetoothInputDevice(Context context, ServiceListener l) {
227bf246ef0abb6ea354fe412b139dec1adb4e5791dMatthew Xie        mContext = context;
2284ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh        mServiceListener = l;
2294ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh        mAdapter = BluetoothAdapter.getDefaultAdapter();
2300f42037eb7b5118015c2caca635538324ccf0ccffredc
2310f42037eb7b5118015c2caca635538324ccf0ccffredc        IBluetoothManager mgr = mAdapter.getBluetoothManager();
2320f42037eb7b5118015c2caca635538324ccf0ccffredc        if (mgr != null) {
2330f42037eb7b5118015c2caca635538324ccf0ccffredc            try {
2340f42037eb7b5118015c2caca635538324ccf0ccffredc                mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
2350f42037eb7b5118015c2caca635538324ccf0ccffredc            } catch (RemoteException e) {
2360f42037eb7b5118015c2caca635538324ccf0ccffredc                Log.e(TAG,"",e);
2370f42037eb7b5118015c2caca635538324ccf0ccffredc            }
2380f42037eb7b5118015c2caca635538324ccf0ccffredc        }
2390f42037eb7b5118015c2caca635538324ccf0ccffredc
240bf246ef0abb6ea354fe412b139dec1adb4e5791dMatthew Xie        if (!context.bindService(new Intent(IBluetoothInputDevice.class.getName()),
241bf246ef0abb6ea354fe412b139dec1adb4e5791dMatthew Xie                                 mConnection, 0)) {
242bf246ef0abb6ea354fe412b139dec1adb4e5791dMatthew Xie            Log.e(TAG, "Could not bind to Bluetooth HID Service");
243545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh        }
244545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh    }
245545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh
2469bb275197df8eb999eab4cdd0a2aff83c2bb2ef6Jaikumar Ganesh    /*package*/ void close() {
247563e414784eb81e4ea4051667d5c8855b17f7534Matthew Xie        if (VDBG) log("close()");
2480f42037eb7b5118015c2caca635538324ccf0ccffredc        IBluetoothManager mgr = mAdapter.getBluetoothManager();
2490f42037eb7b5118015c2caca635538324ccf0ccffredc        if (mgr != null) {
2500f42037eb7b5118015c2caca635538324ccf0ccffredc            try {
2510f42037eb7b5118015c2caca635538324ccf0ccffredc                mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
2520f42037eb7b5118015c2caca635538324ccf0ccffredc            } catch (Exception e) {
2530f42037eb7b5118015c2caca635538324ccf0ccffredc                Log.e(TAG,"",e);
2540f42037eb7b5118015c2caca635538324ccf0ccffredc            }
2550f42037eb7b5118015c2caca635538324ccf0ccffredc        }
2560f42037eb7b5118015c2caca635538324ccf0ccffredc
2570f42037eb7b5118015c2caca635538324ccf0ccffredc        synchronized (mConnection) {
2580f42037eb7b5118015c2caca635538324ccf0ccffredc            if (mService != null) {
2590f42037eb7b5118015c2caca635538324ccf0ccffredc                try {
2600f42037eb7b5118015c2caca635538324ccf0ccffredc                    mService = null;
2610f42037eb7b5118015c2caca635538324ccf0ccffredc                    mContext.unbindService(mConnection);
2620f42037eb7b5118015c2caca635538324ccf0ccffredc                } catch (Exception re) {
2630f42037eb7b5118015c2caca635538324ccf0ccffredc                    Log.e(TAG,"",re);
2640f42037eb7b5118015c2caca635538324ccf0ccffredc                }
2650f42037eb7b5118015c2caca635538324ccf0ccffredc           }
266bf246ef0abb6ea354fe412b139dec1adb4e5791dMatthew Xie        }
2679bb275197df8eb999eab4cdd0a2aff83c2bb2ef6Jaikumar Ganesh        mServiceListener = null;
2689bb275197df8eb999eab4cdd0a2aff83c2bb2ef6Jaikumar Ganesh    }
2699bb275197df8eb999eab4cdd0a2aff83c2bb2ef6Jaikumar Ganesh
2704ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh    /**
271f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * Initiate connection to a profile of the remote bluetooth device.
272f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     *
273f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * <p> The system supports connection to multiple input devices.
274f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     *
275f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * <p> This API returns false in scenarios like the profile on the
276f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * device is already connected or Bluetooth is not turned on.
277f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * When this API returns true, it is guaranteed that
278f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * connection state intent for the profile will be broadcasted with
279f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * the state. Users can get the connection state of the profile
280f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * from this intent.
281f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     *
282f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
283f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * permission.
284f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     *
285f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * @param device Remote Bluetooth Device
286f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * @return false on immediate error,
287f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     *               true otherwise
2884ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh     * @hide
289545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh     */
2904ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh    public boolean connect(BluetoothDevice device) {
2914ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh        if (DBG) log("connect(" + device + ")");
292bf246ef0abb6ea354fe412b139dec1adb4e5791dMatthew Xie        if (mService != null && isEnabled() && isValidDevice(device)) {
2934ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh            try {
294bf246ef0abb6ea354fe412b139dec1adb4e5791dMatthew Xie                return mService.connect(device);
2954ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh            } catch (RemoteException e) {
2964ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh                Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
2974ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh                return false;
298bf246ef0abb6ea354fe412b139dec1adb4e5791dMatthew Xie            }
299545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh        }
3004ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh        if (mService == null) Log.w(TAG, "Proxy not attached to service");
3014ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh        return false;
302545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh    }
303545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh
3044ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh    /**
305f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * Initiate disconnection from a profile
306f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     *
307f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * <p> This API will return false in scenarios like the profile on the
308f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * Bluetooth device is not in connected state etc. When this API returns,
309f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * true, it is guaranteed that the connection state change
310f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * intent will be broadcasted with the state. Users can get the
311f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * disconnection state of the profile from this intent.
312f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     *
313f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * <p> If the disconnection is initiated by a remote device, the state
314f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * will transition from {@link #STATE_CONNECTED} to
315f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * {@link #STATE_DISCONNECTED}. If the disconnect is initiated by the
316f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * host (local) device the state will transition from
317f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * {@link #STATE_CONNECTED} to state {@link #STATE_DISCONNECTING} to
318f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * state {@link #STATE_DISCONNECTED}. The transition to
319f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * {@link #STATE_DISCONNECTING} can be used to distinguish between the
320f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * two scenarios.
321f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     *
322f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
323f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * permission.
324f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     *
325f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * @param device Remote Bluetooth Device
326f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * @return false on immediate error,
327f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     *               true otherwise
3284ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh     * @hide
329545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh     */
3304ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh    public boolean disconnect(BluetoothDevice device) {
3314ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh        if (DBG) log("disconnect(" + device + ")");
332bf246ef0abb6ea354fe412b139dec1adb4e5791dMatthew Xie        if (mService != null && isEnabled() && isValidDevice(device)) {
3334ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh            try {
334bf246ef0abb6ea354fe412b139dec1adb4e5791dMatthew Xie                return mService.disconnect(device);
3354ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh            } catch (RemoteException e) {
3364ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh                Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
3374ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh                return false;
338bf246ef0abb6ea354fe412b139dec1adb4e5791dMatthew Xie            }
339545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh        }
3404ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh        if (mService == null) Log.w(TAG, "Proxy not attached to service");
3414ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh        return false;
342545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh    }
343545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh
3444ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh    /**
3454ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh     * {@inheritDoc}
346545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh     */
3474ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh    public List<BluetoothDevice> getConnectedDevices() {
348563e414784eb81e4ea4051667d5c8855b17f7534Matthew Xie        if (VDBG) log("getConnectedDevices()");
3494ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh        if (mService != null && isEnabled()) {
3504ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh            try {
351bf246ef0abb6ea354fe412b139dec1adb4e5791dMatthew Xie                return mService.getConnectedDevices();
3524ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh            } catch (RemoteException e) {
3534ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh                Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
3544ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh                return new ArrayList<BluetoothDevice>();
355bf246ef0abb6ea354fe412b139dec1adb4e5791dMatthew Xie            }
3564ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh        }
3574ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh        if (mService == null) Log.w(TAG, "Proxy not attached to service");
3584ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh        return new ArrayList<BluetoothDevice>();
359545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh    }
360545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh
3614ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh    /**
3624ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh     * {@inheritDoc}
363545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh     */
3644ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh    public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
365563e414784eb81e4ea4051667d5c8855b17f7534Matthew Xie        if (VDBG) log("getDevicesMatchingStates()");
3664ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh        if (mService != null && isEnabled()) {
3674ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh            try {
368bf246ef0abb6ea354fe412b139dec1adb4e5791dMatthew Xie                return mService.getDevicesMatchingConnectionStates(states);
3694ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh            } catch (RemoteException e) {
3704ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh                Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
3714ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh                return new ArrayList<BluetoothDevice>();
372bf246ef0abb6ea354fe412b139dec1adb4e5791dMatthew Xie            }
373545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh        }
3744ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh        if (mService == null) Log.w(TAG, "Proxy not attached to service");
3754ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh        return new ArrayList<BluetoothDevice>();
376545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh    }
377545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh
3784ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh    /**
3794ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh     * {@inheritDoc}
380545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh     */
3814ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh    public int getConnectionState(BluetoothDevice device) {
382563e414784eb81e4ea4051667d5c8855b17f7534Matthew Xie        if (VDBG) log("getState(" + device + ")");
383bf246ef0abb6ea354fe412b139dec1adb4e5791dMatthew Xie        if (mService != null && isEnabled() && isValidDevice(device)) {
3844ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh            try {
385bf246ef0abb6ea354fe412b139dec1adb4e5791dMatthew Xie                return mService.getConnectionState(device);
3864ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh            } catch (RemoteException e) {
3874ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh                Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
3884ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh                return BluetoothProfile.STATE_DISCONNECTED;
389bf246ef0abb6ea354fe412b139dec1adb4e5791dMatthew Xie            }
390545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh        }
3914ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh        if (mService == null) Log.w(TAG, "Proxy not attached to service");
3924ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh        return BluetoothProfile.STATE_DISCONNECTED;
393545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh    }
394545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh
395545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh    /**
396f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * Set priority of the profile
397f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     *
398f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * <p> The device should already be paired.
399f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     *  Priority can be one of {@link #PRIORITY_ON} or
400f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * {@link #PRIORITY_OFF},
401f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     *
402f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
403f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * permission.
404f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     *
405f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * @param device Paired bluetooth device
406f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * @param priority
407f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * @return true if priority is set, false on error
4084ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh     * @hide
409545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh     */
4104ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh    public boolean setPriority(BluetoothDevice device, int priority) {
4114ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh        if (DBG) log("setPriority(" + device + ", " + priority + ")");
412bf246ef0abb6ea354fe412b139dec1adb4e5791dMatthew Xie        if (mService != null && isEnabled() && isValidDevice(device)) {
4134ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh            if (priority != BluetoothProfile.PRIORITY_OFF &&
4144ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh                priority != BluetoothProfile.PRIORITY_ON) {
4154ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh              return false;
4164ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh            }
4174ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh            try {
418bf246ef0abb6ea354fe412b139dec1adb4e5791dMatthew Xie                return mService.setPriority(device, priority);
4194ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh            } catch (RemoteException e) {
4204ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh                Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
4214ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh                return false;
422bf246ef0abb6ea354fe412b139dec1adb4e5791dMatthew Xie            }
423545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh        }
4244ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh        if (mService == null) Log.w(TAG, "Proxy not attached to service");
4254ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh        return false;
426545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh    }
427545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh
428545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh    /**
429f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * Get the priority of the profile.
430f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     *
431f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * <p> The priority can be any of:
432f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * {@link #PRIORITY_AUTO_CONNECT}, {@link #PRIORITY_OFF},
433f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * {@link #PRIORITY_ON}, {@link #PRIORITY_UNDEFINED}
434f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     *
435f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
436f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     *
437f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * @param device Bluetooth device
438f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * @return priority of the device
4394ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh     * @hide
440545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh     */
4414ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh    public int getPriority(BluetoothDevice device) {
442563e414784eb81e4ea4051667d5c8855b17f7534Matthew Xie        if (VDBG) log("getPriority(" + device + ")");
443bf246ef0abb6ea354fe412b139dec1adb4e5791dMatthew Xie        if (mService != null && isEnabled() && isValidDevice(device)) {
4444ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh            try {
445bf246ef0abb6ea354fe412b139dec1adb4e5791dMatthew Xie                return mService.getPriority(device);
4464ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh            } catch (RemoteException e) {
4474ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh                Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
4484ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh                return BluetoothProfile.PRIORITY_OFF;
449bf246ef0abb6ea354fe412b139dec1adb4e5791dMatthew Xie            }
450545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh        }
4514ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh        if (mService == null) Log.w(TAG, "Proxy not attached to service");
4524ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh        return BluetoothProfile.PRIORITY_OFF;
4534ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh    }
4544ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh
455bf246ef0abb6ea354fe412b139dec1adb4e5791dMatthew Xie    private ServiceConnection mConnection = new ServiceConnection() {
456bf246ef0abb6ea354fe412b139dec1adb4e5791dMatthew Xie        public void onServiceConnected(ComponentName className, IBinder service) {
457bf246ef0abb6ea354fe412b139dec1adb4e5791dMatthew Xie            if (DBG) Log.d(TAG, "Proxy object connected");
458bf246ef0abb6ea354fe412b139dec1adb4e5791dMatthew Xie            mService = IBluetoothInputDevice.Stub.asInterface(service);
459bf246ef0abb6ea354fe412b139dec1adb4e5791dMatthew Xie
460bf246ef0abb6ea354fe412b139dec1adb4e5791dMatthew Xie            if (mServiceListener != null) {
461bf246ef0abb6ea354fe412b139dec1adb4e5791dMatthew Xie                mServiceListener.onServiceConnected(BluetoothProfile.INPUT_DEVICE, BluetoothInputDevice.this);
462bf246ef0abb6ea354fe412b139dec1adb4e5791dMatthew Xie            }
463bf246ef0abb6ea354fe412b139dec1adb4e5791dMatthew Xie        }
464bf246ef0abb6ea354fe412b139dec1adb4e5791dMatthew Xie        public void onServiceDisconnected(ComponentName className) {
465bf246ef0abb6ea354fe412b139dec1adb4e5791dMatthew Xie            if (DBG) Log.d(TAG, "Proxy object disconnected");
466bf246ef0abb6ea354fe412b139dec1adb4e5791dMatthew Xie            mService = null;
467bf246ef0abb6ea354fe412b139dec1adb4e5791dMatthew Xie            if (mServiceListener != null) {
468bf246ef0abb6ea354fe412b139dec1adb4e5791dMatthew Xie                mServiceListener.onServiceDisconnected(BluetoothProfile.INPUT_DEVICE);
469bf246ef0abb6ea354fe412b139dec1adb4e5791dMatthew Xie            }
470bf246ef0abb6ea354fe412b139dec1adb4e5791dMatthew Xie        }
471bf246ef0abb6ea354fe412b139dec1adb4e5791dMatthew Xie    };
472bf246ef0abb6ea354fe412b139dec1adb4e5791dMatthew Xie
4734ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh    private boolean isEnabled() {
4744ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh       if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true;
4754ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh       return false;
4764ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh    }
4774ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh
4784ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh    private boolean isValidDevice(BluetoothDevice device) {
4794ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh       if (device == null) return false;
4804ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh
4814ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh       if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true;
4824ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh       return false;
483545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh    }
484545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh
485349e62f329bbb8edab89356973773a5648f26751Priti Aghera
486349e62f329bbb8edab89356973773a5648f26751Priti Aghera    /**
487349e62f329bbb8edab89356973773a5648f26751Priti Aghera     * Initiate virtual unplug for a HID input device.
488349e62f329bbb8edab89356973773a5648f26751Priti Aghera     *
489349e62f329bbb8edab89356973773a5648f26751Priti Aghera     * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission.
490349e62f329bbb8edab89356973773a5648f26751Priti Aghera     *
491349e62f329bbb8edab89356973773a5648f26751Priti Aghera     * @param device Remote Bluetooth Device
492349e62f329bbb8edab89356973773a5648f26751Priti Aghera     * @return false on immediate error,
493349e62f329bbb8edab89356973773a5648f26751Priti Aghera     *               true otherwise
494349e62f329bbb8edab89356973773a5648f26751Priti Aghera     * @hide
495349e62f329bbb8edab89356973773a5648f26751Priti Aghera     */
496349e62f329bbb8edab89356973773a5648f26751Priti Aghera    public boolean virtualUnplug(BluetoothDevice device) {
497349e62f329bbb8edab89356973773a5648f26751Priti Aghera        if (DBG) log("virtualUnplug(" + device + ")");
498349e62f329bbb8edab89356973773a5648f26751Priti Aghera        if (mService != null && isEnabled() && isValidDevice(device)) {
499349e62f329bbb8edab89356973773a5648f26751Priti Aghera            try {
500349e62f329bbb8edab89356973773a5648f26751Priti Aghera                return mService.virtualUnplug(device);
501349e62f329bbb8edab89356973773a5648f26751Priti Aghera            } catch (RemoteException e) {
502349e62f329bbb8edab89356973773a5648f26751Priti Aghera                Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
503349e62f329bbb8edab89356973773a5648f26751Priti Aghera                return false;
504349e62f329bbb8edab89356973773a5648f26751Priti Aghera            }
505349e62f329bbb8edab89356973773a5648f26751Priti Aghera        }
506349e62f329bbb8edab89356973773a5648f26751Priti Aghera
507349e62f329bbb8edab89356973773a5648f26751Priti Aghera        if (mService == null) Log.w(TAG, "Proxy not attached to service");
508349e62f329bbb8edab89356973773a5648f26751Priti Aghera        return false;
509349e62f329bbb8edab89356973773a5648f26751Priti Aghera
510349e62f329bbb8edab89356973773a5648f26751Priti Aghera    }
511349e62f329bbb8edab89356973773a5648f26751Priti Aghera
512349e62f329bbb8edab89356973773a5648f26751Priti Aghera    /**
513349e62f329bbb8edab89356973773a5648f26751Priti Aghera    * Send Get_Protocol_Mode command to the connected HID input device.
514349e62f329bbb8edab89356973773a5648f26751Priti Aghera    *
515349e62f329bbb8edab89356973773a5648f26751Priti Aghera    * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission.
516349e62f329bbb8edab89356973773a5648f26751Priti Aghera    *
517349e62f329bbb8edab89356973773a5648f26751Priti Aghera    * @param device Remote Bluetooth Device
518349e62f329bbb8edab89356973773a5648f26751Priti Aghera    * @return false on immediate error,
519349e62f329bbb8edab89356973773a5648f26751Priti Aghera    *true otherwise
520349e62f329bbb8edab89356973773a5648f26751Priti Aghera    * @hide
521349e62f329bbb8edab89356973773a5648f26751Priti Aghera    */
522349e62f329bbb8edab89356973773a5648f26751Priti Aghera    public boolean getProtocolMode(BluetoothDevice device) {
523563e414784eb81e4ea4051667d5c8855b17f7534Matthew Xie        if (VDBG) log("getProtocolMode(" + device + ")");
524349e62f329bbb8edab89356973773a5648f26751Priti Aghera        if (mService != null && isEnabled() && isValidDevice(device)) {
525349e62f329bbb8edab89356973773a5648f26751Priti Aghera            try {
526349e62f329bbb8edab89356973773a5648f26751Priti Aghera                return mService.getProtocolMode(device);
527349e62f329bbb8edab89356973773a5648f26751Priti Aghera            } catch (RemoteException e) {
528349e62f329bbb8edab89356973773a5648f26751Priti Aghera                Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
529349e62f329bbb8edab89356973773a5648f26751Priti Aghera                return false;
530349e62f329bbb8edab89356973773a5648f26751Priti Aghera            }
531349e62f329bbb8edab89356973773a5648f26751Priti Aghera        }
532349e62f329bbb8edab89356973773a5648f26751Priti Aghera        if (mService == null) Log.w(TAG, "Proxy not attached to service");
533349e62f329bbb8edab89356973773a5648f26751Priti Aghera            return false;
534349e62f329bbb8edab89356973773a5648f26751Priti Aghera    }
535349e62f329bbb8edab89356973773a5648f26751Priti Aghera
536349e62f329bbb8edab89356973773a5648f26751Priti Aghera    /**
537349e62f329bbb8edab89356973773a5648f26751Priti Aghera     * Send Set_Protocol_Mode command to the connected HID input device.
538349e62f329bbb8edab89356973773a5648f26751Priti Aghera     *
539349e62f329bbb8edab89356973773a5648f26751Priti Aghera     * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission.
540349e62f329bbb8edab89356973773a5648f26751Priti Aghera     *
541349e62f329bbb8edab89356973773a5648f26751Priti Aghera     * @param device Remote Bluetooth Device
542349e62f329bbb8edab89356973773a5648f26751Priti Aghera     * @return false on immediate error,
543349e62f329bbb8edab89356973773a5648f26751Priti Aghera     *               true otherwise
544349e62f329bbb8edab89356973773a5648f26751Priti Aghera     * @hide
545349e62f329bbb8edab89356973773a5648f26751Priti Aghera     */
546349e62f329bbb8edab89356973773a5648f26751Priti Aghera    public boolean setProtocolMode(BluetoothDevice device, int protocolMode) {
547349e62f329bbb8edab89356973773a5648f26751Priti Aghera        if (DBG) log("setProtocolMode(" + device + ")");
548349e62f329bbb8edab89356973773a5648f26751Priti Aghera        if (mService != null && isEnabled() && isValidDevice(device)) {
549349e62f329bbb8edab89356973773a5648f26751Priti Aghera            try {
550349e62f329bbb8edab89356973773a5648f26751Priti Aghera                return mService.setProtocolMode(device, protocolMode);
551349e62f329bbb8edab89356973773a5648f26751Priti Aghera            } catch (RemoteException e) {
552349e62f329bbb8edab89356973773a5648f26751Priti Aghera                Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
553349e62f329bbb8edab89356973773a5648f26751Priti Aghera                return false;
554349e62f329bbb8edab89356973773a5648f26751Priti Aghera            }
555349e62f329bbb8edab89356973773a5648f26751Priti Aghera        }
556349e62f329bbb8edab89356973773a5648f26751Priti Aghera        if (mService == null) Log.w(TAG, "Proxy not attached to service");
557349e62f329bbb8edab89356973773a5648f26751Priti Aghera        return false;
558349e62f329bbb8edab89356973773a5648f26751Priti Aghera    }
559349e62f329bbb8edab89356973773a5648f26751Priti Aghera
560349e62f329bbb8edab89356973773a5648f26751Priti Aghera    /**
561349e62f329bbb8edab89356973773a5648f26751Priti Aghera     * Send Get_Report command to the connected HID input device.
562349e62f329bbb8edab89356973773a5648f26751Priti Aghera     *
563349e62f329bbb8edab89356973773a5648f26751Priti Aghera     * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission.
564349e62f329bbb8edab89356973773a5648f26751Priti Aghera     *
565349e62f329bbb8edab89356973773a5648f26751Priti Aghera     * @param device Remote Bluetooth Device
566349e62f329bbb8edab89356973773a5648f26751Priti Aghera     * @param reportType Report type
567349e62f329bbb8edab89356973773a5648f26751Priti Aghera     * @param reportId Report ID
568349e62f329bbb8edab89356973773a5648f26751Priti Aghera     * @param bufferSize Report receiving buffer size
569349e62f329bbb8edab89356973773a5648f26751Priti Aghera     * @return false on immediate error,
570349e62f329bbb8edab89356973773a5648f26751Priti Aghera     *               true otherwise
571349e62f329bbb8edab89356973773a5648f26751Priti Aghera     * @hide
572349e62f329bbb8edab89356973773a5648f26751Priti Aghera     */
573349e62f329bbb8edab89356973773a5648f26751Priti Aghera    public boolean getReport(BluetoothDevice device, byte reportType, byte reportId, int bufferSize) {
574563e414784eb81e4ea4051667d5c8855b17f7534Matthew Xie        if (VDBG) log("getReport(" + device + "), reportType=" + reportType + " reportId=" + reportId + "bufferSize=" + bufferSize);
575349e62f329bbb8edab89356973773a5648f26751Priti Aghera        if (mService != null && isEnabled() && isValidDevice(device)) {
576349e62f329bbb8edab89356973773a5648f26751Priti Aghera            try {
577349e62f329bbb8edab89356973773a5648f26751Priti Aghera                return mService.getReport(device, reportType, reportId, bufferSize);
578349e62f329bbb8edab89356973773a5648f26751Priti Aghera            } catch (RemoteException e) {
579349e62f329bbb8edab89356973773a5648f26751Priti Aghera                Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
580349e62f329bbb8edab89356973773a5648f26751Priti Aghera                return false;
581349e62f329bbb8edab89356973773a5648f26751Priti Aghera            }
582349e62f329bbb8edab89356973773a5648f26751Priti Aghera        }
583349e62f329bbb8edab89356973773a5648f26751Priti Aghera        if (mService == null) Log.w(TAG, "Proxy not attached to service");
584349e62f329bbb8edab89356973773a5648f26751Priti Aghera        return false;
585349e62f329bbb8edab89356973773a5648f26751Priti Aghera    }
586349e62f329bbb8edab89356973773a5648f26751Priti Aghera
587349e62f329bbb8edab89356973773a5648f26751Priti Aghera    /**
588349e62f329bbb8edab89356973773a5648f26751Priti Aghera     * Send Set_Report command to the connected HID input device.
589349e62f329bbb8edab89356973773a5648f26751Priti Aghera     *
590349e62f329bbb8edab89356973773a5648f26751Priti Aghera     * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission.
591349e62f329bbb8edab89356973773a5648f26751Priti Aghera     *
592349e62f329bbb8edab89356973773a5648f26751Priti Aghera     * @param device Remote Bluetooth Device
593349e62f329bbb8edab89356973773a5648f26751Priti Aghera     * @param reportType Report type
594349e62f329bbb8edab89356973773a5648f26751Priti Aghera     * @param report Report receiving buffer size
595349e62f329bbb8edab89356973773a5648f26751Priti Aghera     * @return false on immediate error,
596349e62f329bbb8edab89356973773a5648f26751Priti Aghera     *               true otherwise
597349e62f329bbb8edab89356973773a5648f26751Priti Aghera     * @hide
598349e62f329bbb8edab89356973773a5648f26751Priti Aghera     */
599349e62f329bbb8edab89356973773a5648f26751Priti Aghera    public boolean setReport(BluetoothDevice device, byte reportType, String report) {
600349e62f329bbb8edab89356973773a5648f26751Priti Aghera        if (DBG) log("setReport(" + device + "), reportType=" + reportType + " report=" + report);
601349e62f329bbb8edab89356973773a5648f26751Priti Aghera        if (mService != null && isEnabled() && isValidDevice(device)) {
602349e62f329bbb8edab89356973773a5648f26751Priti Aghera            try {
603349e62f329bbb8edab89356973773a5648f26751Priti Aghera                return mService.setReport(device, reportType, report);
604349e62f329bbb8edab89356973773a5648f26751Priti Aghera            } catch (RemoteException e) {
605349e62f329bbb8edab89356973773a5648f26751Priti Aghera                Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
606349e62f329bbb8edab89356973773a5648f26751Priti Aghera                return false;
607349e62f329bbb8edab89356973773a5648f26751Priti Aghera            }
608349e62f329bbb8edab89356973773a5648f26751Priti Aghera        }
609349e62f329bbb8edab89356973773a5648f26751Priti Aghera        if (mService == null) Log.w(TAG, "Proxy not attached to service");
610349e62f329bbb8edab89356973773a5648f26751Priti Aghera        return false;
611349e62f329bbb8edab89356973773a5648f26751Priti Aghera    }
612349e62f329bbb8edab89356973773a5648f26751Priti Aghera
613349e62f329bbb8edab89356973773a5648f26751Priti Aghera    /**
614349e62f329bbb8edab89356973773a5648f26751Priti Aghera     * Send Send_Data command to the connected HID input device.
615349e62f329bbb8edab89356973773a5648f26751Priti Aghera     *
616349e62f329bbb8edab89356973773a5648f26751Priti Aghera     * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission.
617349e62f329bbb8edab89356973773a5648f26751Priti Aghera     *
618349e62f329bbb8edab89356973773a5648f26751Priti Aghera     * @param device Remote Bluetooth Device
619349e62f329bbb8edab89356973773a5648f26751Priti Aghera     * @param data Data to send
620349e62f329bbb8edab89356973773a5648f26751Priti Aghera     * @return false on immediate error,
621349e62f329bbb8edab89356973773a5648f26751Priti Aghera     *               true otherwise
622349e62f329bbb8edab89356973773a5648f26751Priti Aghera     * @hide
623349e62f329bbb8edab89356973773a5648f26751Priti Aghera     */
624349e62f329bbb8edab89356973773a5648f26751Priti Aghera    public boolean sendData(BluetoothDevice device, String report) {
625349e62f329bbb8edab89356973773a5648f26751Priti Aghera        if (DBG) log("sendData(" + device + "), report=" + report);
626349e62f329bbb8edab89356973773a5648f26751Priti Aghera        if (mService != null && isEnabled() && isValidDevice(device)) {
627349e62f329bbb8edab89356973773a5648f26751Priti Aghera            try {
628349e62f329bbb8edab89356973773a5648f26751Priti Aghera                return mService.sendData(device, report);
629349e62f329bbb8edab89356973773a5648f26751Priti Aghera            } catch (RemoteException e) {
630349e62f329bbb8edab89356973773a5648f26751Priti Aghera                Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
631349e62f329bbb8edab89356973773a5648f26751Priti Aghera                return false;
632349e62f329bbb8edab89356973773a5648f26751Priti Aghera            }
633349e62f329bbb8edab89356973773a5648f26751Priti Aghera        }
634349e62f329bbb8edab89356973773a5648f26751Priti Aghera        if (mService == null) Log.w(TAG, "Proxy not attached to service");
635349e62f329bbb8edab89356973773a5648f26751Priti Aghera        return false;
636349e62f329bbb8edab89356973773a5648f26751Priti Aghera    }
637545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh    private static void log(String msg) {
6384ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh      Log.d(TAG, msg);
639545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh    }
640545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh}
641