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;
21545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganeshimport android.content.Context;
22545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganeshimport android.os.IBinder;
23545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganeshimport android.os.RemoteException;
24545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganeshimport android.os.ServiceManager;
25545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganeshimport android.util.Log;
26545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh
275a1e4cf83f5be1b5d79e2643fa791aa269b6a4bcJaikumar Ganeshimport java.util.ArrayList;
285a1e4cf83f5be1b5d79e2643fa791aa269b6a4bcJaikumar Ganeshimport java.util.List;
29545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh
304ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh
31545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh/**
324ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh * This class provides the public APIs to control the Bluetooth Input
334ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh * Device Profile.
34545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh *
354ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh *<p>BluetoothInputDevice is a proxy object for controlling the Bluetooth
364ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh * Service via IPC. Use {@link BluetoothAdapter#getProfileProxy} to get
374ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh * the BluetoothInputDevice proxy object.
38545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh *
394ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh *<p>Each method is protected with its appropriate permission.
404ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh *@hide
41545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh */
424ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganeshpublic final class BluetoothInputDevice implements BluetoothProfile {
43545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh    private static final String TAG = "BluetoothInputDevice";
44545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh    private static final boolean DBG = false;
45545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh
46545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh    /**
474ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh     * Intent used to broadcast the change in connection state of the Input
484ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh     * Device profile.
494ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh     *
504ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh     * <p>This intent will have 3 extras:
514ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh     * <ul>
524ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh     *   <li> {@link #EXTRA_STATE} - The current state of the profile. </li>
534ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh     *   <li> {@link #EXTRA_PREVIOUS_STATE}- The previous state of the profile.</li>
544ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh     *   <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li>
554ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh     * </ul>
564ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh     *
574ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh     * <p>{@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} can be any of
584ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh     * {@link #STATE_DISCONNECTED}, {@link #STATE_CONNECTING},
594ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh     * {@link #STATE_CONNECTED}, {@link #STATE_DISCONNECTING}.
604ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh     *
614ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission to
624ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh     * receive.
63545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh     */
644ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
654ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh    public static final String ACTION_CONNECTION_STATE_CHANGED =
664ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh        "android.bluetooth.input.profile.action.CONNECTION_STATE_CHANGED";
67545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh
68fbe807d064ada99211b102914df514aa562256f8Jaikumar Ganesh    /**
69fbe807d064ada99211b102914df514aa562256f8Jaikumar Ganesh     * Return codes for the connect and disconnect Bluez / Dbus calls.
704ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh     * @hide
71fbe807d064ada99211b102914df514aa562256f8Jaikumar Ganesh     */
72fbe807d064ada99211b102914df514aa562256f8Jaikumar Ganesh    public static final int INPUT_DISCONNECT_FAILED_NOT_CONNECTED = 5000;
73fbe807d064ada99211b102914df514aa562256f8Jaikumar Ganesh
744ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh    /**
754ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh     * @hide
764ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh     */
77fbe807d064ada99211b102914df514aa562256f8Jaikumar Ganesh    public static final int INPUT_CONNECT_FAILED_ALREADY_CONNECTED = 5001;
78fbe807d064ada99211b102914df514aa562256f8Jaikumar Ganesh
794ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh    /**
804ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh     * @hide
814ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh     */
82fbe807d064ada99211b102914df514aa562256f8Jaikumar Ganesh    public static final int INPUT_CONNECT_FAILED_ATTEMPT_FAILED = 5002;
83fbe807d064ada99211b102914df514aa562256f8Jaikumar Ganesh
844ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh    /**
854ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh     * @hide
864ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh     */
87fbe807d064ada99211b102914df514aa562256f8Jaikumar Ganesh    public static final int INPUT_OPERATION_GENERIC_FAILURE = 5003;
88fbe807d064ada99211b102914df514aa562256f8Jaikumar Ganesh
894ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh    /**
904ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh     * @hide
914ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh     */
92fbe807d064ada99211b102914df514aa562256f8Jaikumar Ganesh    public static final int INPUT_OPERATION_SUCCESS = 5004;
93fbe807d064ada99211b102914df514aa562256f8Jaikumar Ganesh
944ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh    private ServiceListener mServiceListener;
954ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh    private BluetoothAdapter mAdapter;
964ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh    private IBluetooth mService;
97545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh
98545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh    /**
99545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh     * Create a BluetoothInputDevice proxy object for interacting with the local
1004ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh     * Bluetooth Service which handles the InputDevice profile
1014ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh     *
102545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh     */
1034ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh    /*package*/ BluetoothInputDevice(Context mContext, ServiceListener l) {
104545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh        IBinder b = ServiceManager.getService(BluetoothAdapter.BLUETOOTH_SERVICE);
1054ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh        mServiceListener = l;
1064ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh        mAdapter = BluetoothAdapter.getDefaultAdapter();
107545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh        if (b != null) {
108545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh            mService = IBluetooth.Stub.asInterface(b);
1094ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh            if (mServiceListener != null) {
1104ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh                mServiceListener.onServiceConnected(BluetoothProfile.INPUT_DEVICE, this);
1114ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh            }
112545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh        } else {
113545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh            Log.w(TAG, "Bluetooth Service not available!");
114545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh
115545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh            // Instead of throwing an exception which prevents people from going
116545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh            // into Wireless settings in the emulator. Let it crash later when it is actually used.
117545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh            mService = null;
118545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh        }
119545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh    }
120545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh
1219bb275197df8eb999eab4cdd0a2aff83c2bb2ef6Jaikumar Ganesh    /*package*/ void close() {
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 + ")");
1474ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh        if (mService != null && isEnabled() &&
1484ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh            isValidDevice(device)) {
1494ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh            try {
1504ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh                return mService.connectInputDevice(device);
1514ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh            } catch (RemoteException e) {
1524ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh                Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
1534ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh                return false;
1544ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh            }
155545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh        }
1564ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh        if (mService == null) Log.w(TAG, "Proxy not attached to service");
1574ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh        return false;
158545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh    }
159545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh
1604ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh    /**
161f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * Initiate disconnection from a profile
162f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     *
163f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * <p> This API will return false in scenarios like the profile on the
164f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * Bluetooth device is not in connected state etc. When this API returns,
165f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * true, it is guaranteed that the connection state change
166f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * intent will be broadcasted with the state. Users can get the
167f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * disconnection state of the profile from this intent.
168f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     *
169f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * <p> If the disconnection is initiated by a remote device, the state
170f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * will transition from {@link #STATE_CONNECTED} to
171f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * {@link #STATE_DISCONNECTED}. If the disconnect is initiated by the
172f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * host (local) device the state will transition from
173f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * {@link #STATE_CONNECTED} to state {@link #STATE_DISCONNECTING} to
174f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * state {@link #STATE_DISCONNECTED}. The transition to
175f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * {@link #STATE_DISCONNECTING} can be used to distinguish between the
176f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * two scenarios.
177f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     *
178f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
179f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * permission.
180f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     *
181f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * @param device Remote Bluetooth Device
182f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * @return false on immediate error,
183f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     *               true otherwise
1844ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh     * @hide
185545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh     */
1864ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh    public boolean disconnect(BluetoothDevice device) {
1874ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh        if (DBG) log("disconnect(" + device + ")");
1884ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh        if (mService != null && isEnabled() &&
1894ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh            isValidDevice(device)) {
1904ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh            try {
1914ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh                return mService.disconnectInputDevice(device);
1924ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh            } catch (RemoteException e) {
1934ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh                Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
1944ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh                return false;
1954ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh            }
196545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh        }
1974ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh        if (mService == null) Log.w(TAG, "Proxy not attached to service");
1984ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh        return false;
199545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh    }
200545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh
2014ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh    /**
2024ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh     * {@inheritDoc}
203545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh     */
2044ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh    public List<BluetoothDevice> getConnectedDevices() {
2054ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh        if (DBG) log("getConnectedDevices()");
2064ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh        if (mService != null && isEnabled()) {
2074ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh            try {
2084ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh                return mService.getConnectedInputDevices();
2094ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh            } catch (RemoteException e) {
2104ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh                Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
2114ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh                return new ArrayList<BluetoothDevice>();
2124ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh            }
2134ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh        }
2144ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh        if (mService == null) Log.w(TAG, "Proxy not attached to service");
2154ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh        return new ArrayList<BluetoothDevice>();
216545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh    }
217545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh
2184ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh    /**
2194ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh     * {@inheritDoc}
220545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh     */
2214ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh    public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
2224ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh        if (DBG) log("getDevicesMatchingStates()");
2234ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh        if (mService != null && isEnabled()) {
2244ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh            try {
2254ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh                return mService.getInputDevicesMatchingConnectionStates(states);
2264ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh            } catch (RemoteException e) {
2274ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh                Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
2284ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh                return new ArrayList<BluetoothDevice>();
2294ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh            }
230545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh        }
2314ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh        if (mService == null) Log.w(TAG, "Proxy not attached to service");
2324ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh        return new ArrayList<BluetoothDevice>();
233545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh    }
234545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh
2354ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh    /**
2364ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh     * {@inheritDoc}
237545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh     */
2384ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh    public int getConnectionState(BluetoothDevice device) {
2394ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh        if (DBG) log("getState(" + device + ")");
2404ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh        if (mService != null && isEnabled()
2414ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh            && isValidDevice(device)) {
2424ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh            try {
2434ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh                return mService.getInputDeviceConnectionState(device);
2444ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh            } catch (RemoteException e) {
2454ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh                Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
2464ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh                return BluetoothProfile.STATE_DISCONNECTED;
2474ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh            }
248545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh        }
2494ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh        if (mService == null) Log.w(TAG, "Proxy not attached to service");
2504ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh        return BluetoothProfile.STATE_DISCONNECTED;
251545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh    }
252545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh
253545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh    /**
254f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * Set priority of the profile
255f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     *
256f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * <p> The device should already be paired.
257f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     *  Priority can be one of {@link #PRIORITY_ON} or
258f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * {@link #PRIORITY_OFF},
259f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     *
260f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
261f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * permission.
262f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     *
263f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * @param device Paired bluetooth device
264f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * @param priority
265f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * @return true if priority is set, false on error
2664ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh     * @hide
267545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh     */
2684ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh    public boolean setPriority(BluetoothDevice device, int priority) {
2694ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh        if (DBG) log("setPriority(" + device + ", " + priority + ")");
2704ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh        if (mService != null && isEnabled()
2714ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh            && isValidDevice(device)) {
2724ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh            if (priority != BluetoothProfile.PRIORITY_OFF &&
2734ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh                priority != BluetoothProfile.PRIORITY_ON) {
2744ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh              return false;
2754ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh            }
2764ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh            try {
2774ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh                return mService.setInputDevicePriority(device, priority);
2784ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh            } catch (RemoteException e) {
2794ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh                Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
2804ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh                return false;
2814ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh            }
282545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh        }
2834ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh        if (mService == null) Log.w(TAG, "Proxy not attached to service");
2844ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh        return false;
285545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh    }
286545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh
287545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh    /**
288f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * Get the priority of the profile.
289f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     *
290f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * <p> The priority can be any of:
291f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * {@link #PRIORITY_AUTO_CONNECT}, {@link #PRIORITY_OFF},
292f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * {@link #PRIORITY_ON}, {@link #PRIORITY_UNDEFINED}
293f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     *
294f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
295f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     *
296f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * @param device Bluetooth device
297f8789167e903b637b1dbe8f710e7c66c4cfd74fdJaikumar Ganesh     * @return priority of the device
2984ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh     * @hide
299545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh     */
3004ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh    public int getPriority(BluetoothDevice device) {
3014ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh        if (DBG) log("getPriority(" + device + ")");
3024ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh        if (mService != null && isEnabled()
3034ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh            && isValidDevice(device)) {
3044ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh            try {
3054ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh                return mService.getInputDevicePriority(device);
3064ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh            } catch (RemoteException e) {
3074ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh                Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
3084ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh                return BluetoothProfile.PRIORITY_OFF;
3094ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh            }
310545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh        }
3114ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh        if (mService == null) Log.w(TAG, "Proxy not attached to service");
3124ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh        return BluetoothProfile.PRIORITY_OFF;
3134ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh    }
3144ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh
3154ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh    private boolean isEnabled() {
3164ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh       if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true;
3174ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh       return false;
3184ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh    }
3194ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh
3204ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh    private boolean isValidDevice(BluetoothDevice device) {
3214ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh       if (device == null) return false;
3224ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh
3234ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh       if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true;
3244ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh       return false;
325545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh    }
326545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh
327545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh    private static void log(String msg) {
3284ab0e7746fe74a9e4d75d374f73b7af87420b2f6Jaikumar Ganesh      Log.d(TAG, msg);
329545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh    }
330545e6708adda6859932b55fd824794b1401f5318Jaikumar Ganesh}
331