1066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood/* 2066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood * Copyright (C) 2014 The Android Open Source Project 3066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood * 4066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood * Licensed under the Apache License, Version 2.0 (the "License"); 5066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood * you may not use this file except in compliance with the License. 6066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood * You may obtain a copy of the License at 7066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood * 8066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood * http://www.apache.org/licenses/LICENSE-2.0 9066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood * 10066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood * Unless required by applicable law or agreed to in writing, software 11066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood * distributed under the License is distributed on an "AS IS" BASIS, 12066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood * See the License for the specific language governing permissions and 14066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood * limitations under the License. 15066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood */ 16066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood 17066ad9e16a548218b139424f758b92db7af34af2Mike Lockwoodpackage com.android.bluetooth.avrcp; 18066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood 19066ad9e16a548218b139424f758b92db7af34af2Mike Lockwoodimport android.bluetooth.BluetoothAdapter; 20066ad9e16a548218b139424f758b92db7af34af2Mike Lockwoodimport android.bluetooth.BluetoothAvrcpController; 21066ad9e16a548218b139424f758b92db7af34af2Mike Lockwoodimport android.bluetooth.BluetoothDevice; 22066ad9e16a548218b139424f758b92db7af34af2Mike Lockwoodimport android.bluetooth.BluetoothProfile; 23066ad9e16a548218b139424f758b92db7af34af2Mike Lockwoodimport android.bluetooth.IBluetoothAvrcpController; 24066ad9e16a548218b139424f758b92db7af34af2Mike Lockwoodimport android.content.Intent; 25066ad9e16a548218b139424f758b92db7af34af2Mike Lockwoodimport android.os.Handler; 26066ad9e16a548218b139424f758b92db7af34af2Mike Lockwoodimport android.os.HandlerThread; 27066ad9e16a548218b139424f758b92db7af34af2Mike Lockwoodimport android.os.Looper; 28066ad9e16a548218b139424f758b92db7af34af2Mike Lockwoodimport android.os.Message; 29066ad9e16a548218b139424f758b92db7af34af2Mike Lockwoodimport android.util.Log; 30066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood 31066ad9e16a548218b139424f758b92db7af34af2Mike Lockwoodimport com.android.bluetooth.btservice.ProfileService; 32066ad9e16a548218b139424f758b92db7af34af2Mike Lockwoodimport com.android.bluetooth.Utils; 33066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood 34066ad9e16a548218b139424f758b92db7af34af2Mike Lockwoodimport java.util.ArrayList; 35066ad9e16a548218b139424f758b92db7af34af2Mike Lockwoodimport java.util.List; 36066ad9e16a548218b139424f758b92db7af34af2Mike Lockwoodimport java.util.HashMap; 37066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood 38066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood/** 39066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood * Provides Bluetooth AVRCP Controller profile, as a service in the Bluetooth application. 40066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood * @hide 41066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood */ 42066ad9e16a548218b139424f758b92db7af34af2Mike Lockwoodpublic class AvrcpControllerService extends ProfileService { 43066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood private static final boolean DBG = false; 44066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood private static final String TAG = "AvrcpControllerService"; 45066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood 46066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood private static final int MESSAGE_SEND_PASS_THROUGH_CMD = 1; 47066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood 48066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood private AvrcpMessageHandler mHandler; 49066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood private static AvrcpControllerService sAvrcpControllerService; 50066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood 51066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood private final ArrayList<BluetoothDevice> mConnectedDevices 52066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood = new ArrayList<BluetoothDevice>(); 53066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood 54066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood static { 55066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood classInitNative(); 56066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood } 57066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood 58066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood public AvrcpControllerService() { 59066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood initNative(); 60066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood } 61066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood 62066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood protected String getName() { 63066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood return TAG; 64066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood } 65066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood 66066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood protected IProfileServiceBinder initBinder() { 67066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood return new BluetoothAvrcpControllerBinder(this); 68066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood } 69066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood 70066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood protected boolean start() { 71066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood HandlerThread thread = new HandlerThread("BluetoothAvrcpHandler"); 72066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood thread.start(); 73066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood Looper looper = thread.getLooper(); 74066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood mHandler = new AvrcpMessageHandler(looper); 75066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood 76066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood setAvrcpControllerService(this); 77066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood return true; 78066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood } 79066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood 80066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood protected boolean stop() { 81066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood return true; 82066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood } 83066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood 84066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood protected boolean cleanup() { 85066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood mHandler.removeCallbacksAndMessages(null); 86066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood Looper looper = mHandler.getLooper(); 87066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood if (looper != null) { 88066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood looper.quit(); 89066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood } 90066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood 91066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood clearAvrcpControllerService(); 92066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood 93066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood cleanupNative(); 94066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood 95066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood return true; 96066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood } 97066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood 98066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood //API Methods 99066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood 100066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood public static synchronized AvrcpControllerService getAvrcpControllerService(){ 101066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood if (sAvrcpControllerService != null && sAvrcpControllerService.isAvailable()) { 102066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood if (DBG) Log.d(TAG, "getAvrcpControllerService(): returning " 103066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood + sAvrcpControllerService); 104066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood return sAvrcpControllerService; 105066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood } 106066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood if (DBG) { 107066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood if (sAvrcpControllerService == null) { 108066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood Log.d(TAG, "getAvrcpControllerService(): service is NULL"); 109066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood } else if (!(sAvrcpControllerService.isAvailable())) { 110066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood Log.d(TAG,"getAvrcpControllerService(): service is not available"); 111066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood } 112066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood } 113066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood return null; 114066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood } 115066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood 116066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood private static synchronized void setAvrcpControllerService(AvrcpControllerService instance) { 117066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood if (instance != null && instance.isAvailable()) { 118066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood if (DBG) Log.d(TAG, "setAvrcpControllerService(): set to: " + sAvrcpControllerService); 119066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood sAvrcpControllerService = instance; 120066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood } else { 121066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood if (DBG) { 122066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood if (sAvrcpControllerService == null) { 123066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood Log.d(TAG, "setAvrcpControllerService(): service not available"); 124066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood } else if (!sAvrcpControllerService.isAvailable()) { 125066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood Log.d(TAG,"setAvrcpControllerService(): service is cleaning up"); 126066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood } 127066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood } 128066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood } 129066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood } 130066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood 131066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood private static synchronized void clearAvrcpControllerService() { 132066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood sAvrcpControllerService = null; 133066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood } 134066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood 135066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood public List<BluetoothDevice> getConnectedDevices() { 136066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 137066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood return mConnectedDevices; 138066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood } 139066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood 140066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { 141066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 142066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood for (int i = 0; i < states.length; i++) { 143066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood if (states[i] == BluetoothProfile.STATE_CONNECTED) { 144066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood return mConnectedDevices; 145066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood } 146066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood } 147066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood return new ArrayList<BluetoothDevice>(); 148066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood } 149066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood 150066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood int getConnectionState(BluetoothDevice device) { 151066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 152066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood return (mConnectedDevices.contains(device) ? BluetoothProfile.STATE_CONNECTED 153066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood : BluetoothProfile.STATE_DISCONNECTED); 154066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood } 155066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood 156066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood public void sendPassThroughCmd(BluetoothDevice device, int keyCode, int keyState) { 157066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood if (DBG) Log.d(TAG, "sendPassThroughCmd"); 158066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood Log.v(TAG, "keyCode: " + keyCode + " keyState: " + keyState); 159066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood if (device == null) { 160066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood throw new NullPointerException("device == null"); 161066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood } 162066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 163066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood Message msg = mHandler.obtainMessage(MESSAGE_SEND_PASS_THROUGH_CMD, 164066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood keyCode, keyState, device); 165066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood mHandler.sendMessage(msg); 166066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood } 167066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood 168066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood //Binder object: Must be static class or memory leak may occur 169066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood private static class BluetoothAvrcpControllerBinder extends IBluetoothAvrcpController.Stub 170066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood implements IProfileServiceBinder { 171066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood private AvrcpControllerService mService; 172066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood 173066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood private AvrcpControllerService getService() { 174066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood if (!Utils.checkCaller()) { 175066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood Log.w(TAG,"AVRCP call not allowed for non-active user"); 176066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood return null; 177066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood } 178066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood 179066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood if (mService != null && mService.isAvailable()) { 180066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood return mService; 181066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood } 182066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood return null; 183066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood } 184066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood 185066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood BluetoothAvrcpControllerBinder(AvrcpControllerService svc) { 186066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood mService = svc; 187066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood } 188066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood 189066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood public boolean cleanup() { 190066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood mService = null; 191066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood return true; 192066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood } 193066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood 194066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood public List<BluetoothDevice> getConnectedDevices() { 195066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood AvrcpControllerService service = getService(); 196066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood if (service == null) return new ArrayList<BluetoothDevice>(0); 197066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood return service.getConnectedDevices(); 198066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood } 199066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood 200066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { 201066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood AvrcpControllerService service = getService(); 202066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood if (service == null) return new ArrayList<BluetoothDevice>(0); 203066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood return service.getDevicesMatchingConnectionStates(states); 204066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood } 205066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood 206066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood public int getConnectionState(BluetoothDevice device) { 207066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood AvrcpControllerService service = getService(); 208066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood if (service == null) return BluetoothProfile.STATE_DISCONNECTED; 209066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood return service.getConnectionState(device); 210066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood } 211066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood 212066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood public void sendPassThroughCmd(BluetoothDevice device, int keyCode, int keyState) { 213066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood Log.v(TAG,"Binder Call: sendPassThroughCmd"); 214066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood AvrcpControllerService service = getService(); 215066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood if (service == null) return; 216066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood service.sendPassThroughCmd(device, keyCode, keyState); 217066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood } 218066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood }; 219066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood 220066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood /** Handles Avrcp messages. */ 221066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood private final class AvrcpMessageHandler extends Handler { 222066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood private AvrcpMessageHandler(Looper looper) { 223066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood super(looper); 224066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood } 225066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood 226066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood @Override 227066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood public void handleMessage(Message msg) { 228066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood switch (msg.what) { 229066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood case MESSAGE_SEND_PASS_THROUGH_CMD: 230066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood if (DBG) Log.v(TAG, "MESSAGE_SEND_PASS_THROUGH_CMD"); 231066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood BluetoothDevice device = (BluetoothDevice)msg.obj; 232066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood sendPassThroughCommandNative(getByteAddress(device), msg.arg1, msg.arg2); 233066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood break; 234066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood } 235066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood } 236066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood } 237066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood 238066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood private void onConnectionStateChanged(boolean connected, byte[] address) { 239066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood BluetoothDevice device = BluetoothAdapter.getDefaultAdapter().getRemoteDevice 240066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood (Utils.getAddressStringFromByte(address)); 241066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood Log.d(TAG, "onConnectionStateChanged " + connected + " " + device); 242066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood Intent intent = new Intent(BluetoothAvrcpController.ACTION_CONNECTION_STATE_CHANGED); 243066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood int oldState = (mConnectedDevices.contains(device) ? BluetoothProfile.STATE_CONNECTED 244066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood : BluetoothProfile.STATE_DISCONNECTED); 245066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood int newState = (connected ? BluetoothProfile.STATE_CONNECTED 246066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood : BluetoothProfile.STATE_DISCONNECTED); 247066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood intent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, oldState); 248066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood intent.putExtra(BluetoothProfile.EXTRA_STATE, newState); 249066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device); 250066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood// intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 251066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood sendBroadcast(intent, ProfileService.BLUETOOTH_PERM); 252066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood if (connected && oldState == BluetoothProfile.STATE_DISCONNECTED) { 253066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood mConnectedDevices.add(device); 254066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood } else if (!connected && oldState == BluetoothProfile.STATE_CONNECTED) { 255066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood mConnectedDevices.remove(device); 256066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood } 257066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood } 258066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood 259066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood private void handlePassthroughRsp(int id, int keyState) { 260066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood Log.d(TAG, "passthrough response received as: key: " 261066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood + id + " state: " + keyState); 262066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood } 263066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood 264066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood private byte[] getByteAddress(BluetoothDevice device) { 265066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood return Utils.getBytesFromAddress(device.getAddress()); 266066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood } 267066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood 268066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood private native static void classInitNative(); 269066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood private native void initNative(); 270066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood private native void cleanupNative(); 271066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood private native boolean sendPassThroughCommandNative(byte[] address, int keyCode, int keyState); 272066ad9e16a548218b139424f758b92db7af34af2Mike Lockwood} 273