BluetoothInputDevice.java revision bf246ef0abb6ea354fe412b139dec1adb4e5791d
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;
27545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganeshimport android.util.Log;
28545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh
295a1e4cf83f5be1b5d79e2643fa791aa269b6a4bcJaikumar Ganeshimport java.util.ArrayList;
305a1e4cf83f5be1b5d79e2643fa791aa269b6a4bcJaikumar Ganeshimport java.util.List;
31545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh
324ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh
33545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh/**
344ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh * This class provides the public APIs to control the Bluetooth Input
354ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh * Device Profile.
36545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh *
374ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh *<p>BluetoothInputDevice is a proxy object for controlling the Bluetooth
384ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh * Service via IPC. Use {@link BluetoothAdapter#getProfileProxy} to get
394ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh * the BluetoothInputDevice proxy object.
40545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh *
414ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh *<p>Each method is protected with its appropriate permission.
424ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh *@hide
43545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh */
444ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganeshpublic final class BluetoothInputDevice implements BluetoothProfile {
45545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh    private static final String TAG = "BluetoothInputDevice";
46545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh    private static final boolean DBG = false;
47545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh
48545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh    /**
494ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh     * Intent used to broadcast the change in connection state of the Input
504ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh     * Device profile.
514ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh     *
524ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh     * <p>This intent will have 3 extras:
534ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh     * <ul>
544ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh     *   <li> {@link #EXTRA_STATE} - The current state of the profile. </li>
554ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh     *   <li> {@link #EXTRA_PREVIOUS_STATE}- The previous state of the profile.</li>
564ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh     *   <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li>
574ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh     * </ul>
584ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh     *
594ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh     * <p>{@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} can be any of
604ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh     * {@link #STATE_DISCONNECTED}, {@link #STATE_CONNECTING},
614ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh     * {@link #STATE_CONNECTED}, {@link #STATE_DISCONNECTING}.
624ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh     *
634ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission to
644ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh     * receive.
65545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh     */
664ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
674ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh    public static final String ACTION_CONNECTION_STATE_CHANGED =
684ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh        "android.bluetooth.input.profile.action.CONNECTION_STATE_CHANGED";
69545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh
70fbe807d064ada99211b102914df514aa562256f8Jaikumar Ganesh    /**
71fbe807d064ada99211b102914df514aa562256f8Jaikumar Ganesh     * Return codes for the connect and disconnect Bluez / Dbus calls.
724ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh     * @hide
73fbe807d064ada99211b102914df514aa562256f8Jaikumar Ganesh     */
74fbe807d064ada99211b102914df514aa562256f8Jaikumar Ganesh    public static final int INPUT_DISCONNECT_FAILED_NOT_CONNECTED = 5000;
75fbe807d064ada99211b102914df514aa562256f8Jaikumar Ganesh
764ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh    /**
774ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh     * @hide
784ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh     */
79fbe807d064ada99211b102914df514aa562256f8Jaikumar Ganesh    public static final int INPUT_CONNECT_FAILED_ALREADY_CONNECTED = 5001;
80fbe807d064ada99211b102914df514aa562256f8Jaikumar Ganesh
814ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh    /**
824ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh     * @hide
834ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh     */
84fbe807d064ada99211b102914df514aa562256f8Jaikumar Ganesh    public static final int INPUT_CONNECT_FAILED_ATTEMPT_FAILED = 5002;
85fbe807d064ada99211b102914df514aa562256f8Jaikumar Ganesh
864ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh    /**
874ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh     * @hide
884ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh     */
89fbe807d064ada99211b102914df514aa562256f8Jaikumar Ganesh    public static final int INPUT_OPERATION_GENERIC_FAILURE = 5003;
90fbe807d064ada99211b102914df514aa562256f8Jaikumar Ganesh
914ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh    /**
924ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh     * @hide
934ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh     */
94fbe807d064ada99211b102914df514aa562256f8Jaikumar Ganesh    public static final int INPUT_OPERATION_SUCCESS = 5004;
95fbe807d064ada99211b102914df514aa562256f8Jaikumar Ganesh
96bf246ef0abb6ea354fe412b139dec1adb4e5791dMatthew Xie    private Context mContext;
974ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh    private ServiceListener mServiceListener;
984ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh    private BluetoothAdapter mAdapter;
99bf246ef0abb6ea354fe412b139dec1adb4e5791dMatthew Xie    private IBluetoothInputDevice mService;
100545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh
101545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh    /**
102545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh     * Create a BluetoothInputDevice proxy object for interacting with the local
1034ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh     * Bluetooth Service which handles the InputDevice profile
1044ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh     *
105545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh     */
106bf246ef0abb6ea354fe412b139dec1adb4e5791dMatthew Xie    /*package*/ BluetoothInputDevice(Context context, ServiceListener l) {
107bf246ef0abb6ea354fe412b139dec1adb4e5791dMatthew Xie        mContext = context;
1084ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh        mServiceListener = l;
1094ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh        mAdapter = BluetoothAdapter.getDefaultAdapter();
110bf246ef0abb6ea354fe412b139dec1adb4e5791dMatthew Xie        if (!context.bindService(new Intent(IBluetoothInputDevice.class.getName()),
111bf246ef0abb6ea354fe412b139dec1adb4e5791dMatthew Xie                                 mConnection, 0)) {
112bf246ef0abb6ea354fe412b139dec1adb4e5791dMatthew Xie            Log.e(TAG, "Could not bind to Bluetooth HID Service");
113545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh        }
114545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh    }
115545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh
1169bb275197df8eb999eab4cdd0a2aff83c2bb2ef6Jaikumar Ganesh    /*package*/ void close() {
117bf246ef0abb6ea354fe412b139dec1adb4e5791dMatthew Xie        if (DBG) log("close()");
118bf246ef0abb6ea354fe412b139dec1adb4e5791dMatthew Xie        if (mConnection != null) {
119bf246ef0abb6ea354fe412b139dec1adb4e5791dMatthew Xie            mContext.unbindService(mConnection);
120bf246ef0abb6ea354fe412b139dec1adb4e5791dMatthew Xie            mConnection = null;
121bf246ef0abb6ea354fe412b139dec1adb4e5791dMatthew Xie        }
1229bb275197df8eb999eab4cdd0a2aff83c2bb2ef6Jaikumar Ganesh        mServiceListener = null;
1239bb275197df8eb999eab4cdd0a2aff83c2bb2ef6Jaikumar Ganesh    }
1249bb275197df8eb999eab4cdd0a2aff83c2bb2ef6Jaikumar Ganesh
1254ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh    /**
126f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * Initiate connection to a profile of the remote bluetooth device.
127f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     *
128f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * <p> The system supports connection to multiple input devices.
129f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     *
130f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * <p> This API returns false in scenarios like the profile on the
131f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * device is already connected or Bluetooth is not turned on.
132f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * When this API returns true, it is guaranteed that
133f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * connection state intent for the profile will be broadcasted with
134f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * the state. Users can get the connection state of the profile
135f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * from this intent.
136f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     *
137f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
138f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * permission.
139f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     *
140f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * @param device Remote Bluetooth Device
141f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * @return false on immediate error,
142f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     *               true otherwise
1434ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh     * @hide
144545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh     */
1454ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh    public boolean connect(BluetoothDevice device) {
1464ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh        if (DBG) log("connect(" + device + ")");
147bf246ef0abb6ea354fe412b139dec1adb4e5791dMatthew Xie        if (mService != null && isEnabled() && isValidDevice(device)) {
1484ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh            try {
149bf246ef0abb6ea354fe412b139dec1adb4e5791dMatthew Xie                return mService.connect(device);
1504ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh            } catch (RemoteException e) {
1514ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh                Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
1524ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh                return false;
153bf246ef0abb6ea354fe412b139dec1adb4e5791dMatthew Xie            }
154545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh        }
1554ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh        if (mService == null) Log.w(TAG, "Proxy not attached to service");
1564ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh        return false;
157545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh    }
158545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh
1594ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh    /**
160f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * Initiate disconnection from a profile
161f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     *
162f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * <p> This API will return false in scenarios like the profile on the
163f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * Bluetooth device is not in connected state etc. When this API returns,
164f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * true, it is guaranteed that the connection state change
165f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * intent will be broadcasted with the state. Users can get the
166f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * disconnection state of the profile from this intent.
167f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     *
168f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * <p> If the disconnection is initiated by a remote device, the state
169f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * will transition from {@link #STATE_CONNECTED} to
170f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * {@link #STATE_DISCONNECTED}. If the disconnect is initiated by the
171f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * host (local) device the state will transition from
172f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * {@link #STATE_CONNECTED} to state {@link #STATE_DISCONNECTING} to
173f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * state {@link #STATE_DISCONNECTED}. The transition to
174f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * {@link #STATE_DISCONNECTING} can be used to distinguish between the
175f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * two scenarios.
176f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     *
177f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
178f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * permission.
179f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     *
180f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * @param device Remote Bluetooth Device
181f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * @return false on immediate error,
182f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     *               true otherwise
1834ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh     * @hide
184545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh     */
1854ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh    public boolean disconnect(BluetoothDevice device) {
1864ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh        if (DBG) log("disconnect(" + device + ")");
187bf246ef0abb6ea354fe412b139dec1adb4e5791dMatthew Xie        if (mService != null && isEnabled() && isValidDevice(device)) {
1884ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh            try {
189bf246ef0abb6ea354fe412b139dec1adb4e5791dMatthew Xie                return mService.disconnect(device);
1904ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh            } catch (RemoteException e) {
1914ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh                Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
1924ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh                return false;
193bf246ef0abb6ea354fe412b139dec1adb4e5791dMatthew Xie            }
194545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh        }
1954ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh        if (mService == null) Log.w(TAG, "Proxy not attached to service");
1964ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh        return false;
197545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh    }
198545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh
1994ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh    /**
2004ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh     * {@inheritDoc}
201545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh     */
2024ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh    public List<BluetoothDevice> getConnectedDevices() {
2034ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh        if (DBG) log("getConnectedDevices()");
2044ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh        if (mService != null && isEnabled()) {
2054ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh            try {
206bf246ef0abb6ea354fe412b139dec1adb4e5791dMatthew Xie                return mService.getConnectedDevices();
2074ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh            } catch (RemoteException e) {
2084ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh                Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
2094ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh                return new ArrayList<BluetoothDevice>();
210bf246ef0abb6ea354fe412b139dec1adb4e5791dMatthew Xie            }
2114ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh        }
2124ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh        if (mService == null) Log.w(TAG, "Proxy not attached to service");
2134ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh        return new ArrayList<BluetoothDevice>();
214545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh    }
215545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh
2164ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh    /**
2174ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh     * {@inheritDoc}
218545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh     */
2194ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh    public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
2204ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh        if (DBG) log("getDevicesMatchingStates()");
2214ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh        if (mService != null && isEnabled()) {
2224ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh            try {
223bf246ef0abb6ea354fe412b139dec1adb4e5791dMatthew Xie                return mService.getDevicesMatchingConnectionStates(states);
2244ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh            } catch (RemoteException e) {
2254ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh                Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
2264ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh                return new ArrayList<BluetoothDevice>();
227bf246ef0abb6ea354fe412b139dec1adb4e5791dMatthew Xie            }
228545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh        }
2294ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh        if (mService == null) Log.w(TAG, "Proxy not attached to service");
2304ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh        return new ArrayList<BluetoothDevice>();
231545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh    }
232545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh
2334ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh    /**
2344ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh     * {@inheritDoc}
235545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh     */
2364ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh    public int getConnectionState(BluetoothDevice device) {
2374ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh        if (DBG) log("getState(" + device + ")");
238bf246ef0abb6ea354fe412b139dec1adb4e5791dMatthew Xie        if (mService != null && isEnabled() && isValidDevice(device)) {
2394ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh            try {
240bf246ef0abb6ea354fe412b139dec1adb4e5791dMatthew Xie                return mService.getConnectionState(device);
2414ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh            } catch (RemoteException e) {
2424ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh                Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
2434ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh                return BluetoothProfile.STATE_DISCONNECTED;
244bf246ef0abb6ea354fe412b139dec1adb4e5791dMatthew Xie            }
245545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh        }
2464ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh        if (mService == null) Log.w(TAG, "Proxy not attached to service");
2474ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh        return BluetoothProfile.STATE_DISCONNECTED;
248545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh    }
249545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh
250545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh    /**
251f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * Set priority of the profile
252f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     *
253f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * <p> The device should already be paired.
254f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     *  Priority can be one of {@link #PRIORITY_ON} or
255f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * {@link #PRIORITY_OFF},
256f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     *
257f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
258f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * permission.
259f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     *
260f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * @param device Paired bluetooth device
261f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * @param priority
262f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * @return true if priority is set, false on error
2634ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh     * @hide
264545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh     */
2654ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh    public boolean setPriority(BluetoothDevice device, int priority) {
2664ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh        if (DBG) log("setPriority(" + device + ", " + priority + ")");
267bf246ef0abb6ea354fe412b139dec1adb4e5791dMatthew Xie        if (mService != null && isEnabled() && isValidDevice(device)) {
2684ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh            if (priority != BluetoothProfile.PRIORITY_OFF &&
2694ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh                priority != BluetoothProfile.PRIORITY_ON) {
2704ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh              return false;
2714ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh            }
2724ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh            try {
273bf246ef0abb6ea354fe412b139dec1adb4e5791dMatthew Xie                return mService.setPriority(device, priority);
2744ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh            } catch (RemoteException e) {
2754ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh                Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
2764ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh                return false;
277bf246ef0abb6ea354fe412b139dec1adb4e5791dMatthew Xie            }
278545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh        }
2794ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh        if (mService == null) Log.w(TAG, "Proxy not attached to service");
2804ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh        return false;
281545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh    }
282545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh
283545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh    /**
284f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * Get the priority of the profile.
285f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     *
286f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * <p> The priority can be any of:
287f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * {@link #PRIORITY_AUTO_CONNECT}, {@link #PRIORITY_OFF},
288f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * {@link #PRIORITY_ON}, {@link #PRIORITY_UNDEFINED}
289f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     *
290f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
291f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     *
292f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * @param device Bluetooth device
293f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * @return priority of the device
2944ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh     * @hide
295545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh     */
2964ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh    public int getPriority(BluetoothDevice device) {
2974ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh        if (DBG) log("getPriority(" + device + ")");
298bf246ef0abb6ea354fe412b139dec1adb4e5791dMatthew Xie        if (mService != null && isEnabled() && isValidDevice(device)) {
2994ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh            try {
300bf246ef0abb6ea354fe412b139dec1adb4e5791dMatthew Xie                return mService.getPriority(device);
3014ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh            } catch (RemoteException e) {
3024ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh                Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
3034ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh                return BluetoothProfile.PRIORITY_OFF;
304bf246ef0abb6ea354fe412b139dec1adb4e5791dMatthew Xie            }
305545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh        }
3064ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh        if (mService == null) Log.w(TAG, "Proxy not attached to service");
3074ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh        return BluetoothProfile.PRIORITY_OFF;
3084ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh    }
3094ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh
310bf246ef0abb6ea354fe412b139dec1adb4e5791dMatthew Xie    private ServiceConnection mConnection = new ServiceConnection() {
311bf246ef0abb6ea354fe412b139dec1adb4e5791dMatthew Xie        public void onServiceConnected(ComponentName className, IBinder service) {
312bf246ef0abb6ea354fe412b139dec1adb4e5791dMatthew Xie            if (DBG) Log.d(TAG, "Proxy object connected");
313bf246ef0abb6ea354fe412b139dec1adb4e5791dMatthew Xie            mService = IBluetoothInputDevice.Stub.asInterface(service);
314bf246ef0abb6ea354fe412b139dec1adb4e5791dMatthew Xie
315bf246ef0abb6ea354fe412b139dec1adb4e5791dMatthew Xie            if (mServiceListener != null) {
316bf246ef0abb6ea354fe412b139dec1adb4e5791dMatthew Xie                mServiceListener.onServiceConnected(BluetoothProfile.INPUT_DEVICE, BluetoothInputDevice.this);
317bf246ef0abb6ea354fe412b139dec1adb4e5791dMatthew Xie            }
318bf246ef0abb6ea354fe412b139dec1adb4e5791dMatthew Xie        }
319bf246ef0abb6ea354fe412b139dec1adb4e5791dMatthew Xie        public void onServiceDisconnected(ComponentName className) {
320bf246ef0abb6ea354fe412b139dec1adb4e5791dMatthew Xie            if (DBG) Log.d(TAG, "Proxy object disconnected");
321bf246ef0abb6ea354fe412b139dec1adb4e5791dMatthew Xie            mService = null;
322bf246ef0abb6ea354fe412b139dec1adb4e5791dMatthew Xie            if (mServiceListener != null) {
323bf246ef0abb6ea354fe412b139dec1adb4e5791dMatthew Xie                mServiceListener.onServiceDisconnected(BluetoothProfile.INPUT_DEVICE);
324bf246ef0abb6ea354fe412b139dec1adb4e5791dMatthew Xie            }
325bf246ef0abb6ea354fe412b139dec1adb4e5791dMatthew Xie        }
326bf246ef0abb6ea354fe412b139dec1adb4e5791dMatthew Xie    };
327bf246ef0abb6ea354fe412b139dec1adb4e5791dMatthew Xie
3284ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh    private boolean isEnabled() {
3294ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh       if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true;
3304ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh       return false;
3314ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh    }
3324ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh
3334ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh    private boolean isValidDevice(BluetoothDevice device) {
3344ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh       if (device == null) return false;
3354ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh
3364ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh       if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true;
3374ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh       return false;
338545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh    }
339545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh
340545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh    private static void log(String msg) {
3414ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh      Log.d(TAG, msg);
342545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh    }
343545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh}
344