1510203ee5e3350758dae4bf9af05b1585029af7dWally Yau/* 2510203ee5e3350758dae4bf9af05b1585029af7dWally Yau * Copyright (C) 2014 The Android Open Source Project 3510203ee5e3350758dae4bf9af05b1585029af7dWally Yau * 4510203ee5e3350758dae4bf9af05b1585029af7dWally Yau * Licensed under the Apache License, Version 2.0 (the "License"); 5510203ee5e3350758dae4bf9af05b1585029af7dWally Yau * you may not use this file except in compliance with the License. 6510203ee5e3350758dae4bf9af05b1585029af7dWally Yau * You may obtain a copy of the License at 7510203ee5e3350758dae4bf9af05b1585029af7dWally Yau * 8510203ee5e3350758dae4bf9af05b1585029af7dWally Yau * http://www.apache.org/licenses/LICENSE-2.0 9510203ee5e3350758dae4bf9af05b1585029af7dWally Yau * 10510203ee5e3350758dae4bf9af05b1585029af7dWally Yau * Unless required by applicable law or agreed to in writing, software 11510203ee5e3350758dae4bf9af05b1585029af7dWally Yau * distributed under the License is distributed on an "AS IS" BASIS, 12510203ee5e3350758dae4bf9af05b1585029af7dWally Yau * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13510203ee5e3350758dae4bf9af05b1585029af7dWally Yau * See the License for the specific language governing permissions and 14510203ee5e3350758dae4bf9af05b1585029af7dWally Yau * limitations under the License. 15510203ee5e3350758dae4bf9af05b1585029af7dWally Yau */ 16510203ee5e3350758dae4bf9af05b1585029af7dWally Yau 17510203ee5e3350758dae4bf9af05b1585029af7dWally Yaupackage com.android.tv.settings.accessories; 18510203ee5e3350758dae4bf9af05b1585029af7dWally Yau 19510203ee5e3350758dae4bf9af05b1585029af7dWally Yauimport android.bluetooth.BluetoothA2dp; 20510203ee5e3350758dae4bf9af05b1585029af7dWally Yauimport android.bluetooth.BluetoothAdapter; 21510203ee5e3350758dae4bf9af05b1585029af7dWally Yauimport android.bluetooth.BluetoothDevice; 22510203ee5e3350758dae4bf9af05b1585029af7dWally Yauimport android.bluetooth.BluetoothProfile; 23510203ee5e3350758dae4bf9af05b1585029af7dWally Yauimport android.content.BroadcastReceiver; 24510203ee5e3350758dae4bf9af05b1585029af7dWally Yauimport android.content.Context; 25510203ee5e3350758dae4bf9af05b1585029af7dWally Yauimport android.content.Intent; 26510203ee5e3350758dae4bf9af05b1585029af7dWally Yauimport android.content.IntentFilter; 27510203ee5e3350758dae4bf9af05b1585029af7dWally Yauimport android.util.Log; 28510203ee5e3350758dae4bf9af05b1585029af7dWally Yau 29510203ee5e3350758dae4bf9af05b1585029af7dWally Yau 30510203ee5e3350758dae4bf9af05b1585029af7dWally Yaupublic class BluetoothA2dpConnector implements BluetoothDevicePairer.BluetoothConnector { 31510203ee5e3350758dae4bf9af05b1585029af7dWally Yau 3280ce1531cd5ea91a5332f923b9a434d79e81e22fTony Mantler public static final String TAG = "BluetoothA2dpConnector"; 33510203ee5e3350758dae4bf9af05b1585029af7dWally Yau 34510203ee5e3350758dae4bf9af05b1585029af7dWally Yau private static final boolean DEBUG = false; 35510203ee5e3350758dae4bf9af05b1585029af7dWally Yau 36510203ee5e3350758dae4bf9af05b1585029af7dWally Yau private Context mContext; 37510203ee5e3350758dae4bf9af05b1585029af7dWally Yau private BluetoothDevice mTarget; 38510203ee5e3350758dae4bf9af05b1585029af7dWally Yau private BluetoothDevicePairer.OpenConnectionCallback mOpenConnectionCallback; 39510203ee5e3350758dae4bf9af05b1585029af7dWally Yau private BluetoothA2dp mA2dpProfile; 40510203ee5e3350758dae4bf9af05b1585029af7dWally Yau private boolean mConnectionStateReceiverRegistered = false; 41510203ee5e3350758dae4bf9af05b1585029af7dWally Yau 42510203ee5e3350758dae4bf9af05b1585029af7dWally Yau private BroadcastReceiver mConnectionStateReceiver = new BroadcastReceiver() { 43510203ee5e3350758dae4bf9af05b1585029af7dWally Yau @Override 44510203ee5e3350758dae4bf9af05b1585029af7dWally Yau public void onReceive(Context context, Intent intent) { 45510203ee5e3350758dae4bf9af05b1585029af7dWally Yau BluetoothDevice device = (BluetoothDevice) intent.getParcelableExtra( 46510203ee5e3350758dae4bf9af05b1585029af7dWally Yau BluetoothDevice.EXTRA_DEVICE); 47510203ee5e3350758dae4bf9af05b1585029af7dWally Yau if (DEBUG) { 48510203ee5e3350758dae4bf9af05b1585029af7dWally Yau Log.d(TAG, "There was a connection status change for: " + device.getAddress()); 49510203ee5e3350758dae4bf9af05b1585029af7dWally Yau } 50510203ee5e3350758dae4bf9af05b1585029af7dWally Yau 51510203ee5e3350758dae4bf9af05b1585029af7dWally Yau if (device.equals(mTarget)) { 52510203ee5e3350758dae4bf9af05b1585029af7dWally Yau int previousState = intent.getIntExtra( 53510203ee5e3350758dae4bf9af05b1585029af7dWally Yau BluetoothA2dp.EXTRA_PREVIOUS_STATE, 54510203ee5e3350758dae4bf9af05b1585029af7dWally Yau BluetoothA2dp.STATE_CONNECTING); 55510203ee5e3350758dae4bf9af05b1585029af7dWally Yau int state = intent.getIntExtra(BluetoothA2dp.EXTRA_STATE, 56510203ee5e3350758dae4bf9af05b1585029af7dWally Yau BluetoothA2dp.STATE_CONNECTING); 57510203ee5e3350758dae4bf9af05b1585029af7dWally Yau 58510203ee5e3350758dae4bf9af05b1585029af7dWally Yau if (DEBUG) { 59510203ee5e3350758dae4bf9af05b1585029af7dWally Yau Log.d(TAG, "Connection states: old = " + previousState + ", new = " + state); 60510203ee5e3350758dae4bf9af05b1585029af7dWally Yau } 61510203ee5e3350758dae4bf9af05b1585029af7dWally Yau 62510203ee5e3350758dae4bf9af05b1585029af7dWally Yau if (previousState == BluetoothA2dp.STATE_CONNECTING) { 63510203ee5e3350758dae4bf9af05b1585029af7dWally Yau if (state == BluetoothA2dp.STATE_CONNECTED) { 64510203ee5e3350758dae4bf9af05b1585029af7dWally Yau mOpenConnectionCallback.succeeded(); 65510203ee5e3350758dae4bf9af05b1585029af7dWally Yau } else if (state == BluetoothA2dp.STATE_DISCONNECTED) { 66510203ee5e3350758dae4bf9af05b1585029af7dWally Yau Log.d(TAG, "Failed to connect"); 67510203ee5e3350758dae4bf9af05b1585029af7dWally Yau mOpenConnectionCallback.failed(); 68510203ee5e3350758dae4bf9af05b1585029af7dWally Yau } 69510203ee5e3350758dae4bf9af05b1585029af7dWally Yau 70510203ee5e3350758dae4bf9af05b1585029af7dWally Yau unregisterConnectionStateReceiver(); 71510203ee5e3350758dae4bf9af05b1585029af7dWally Yau closeA2dpProfileProxy(); 72510203ee5e3350758dae4bf9af05b1585029af7dWally Yau } 73510203ee5e3350758dae4bf9af05b1585029af7dWally Yau } 74510203ee5e3350758dae4bf9af05b1585029af7dWally Yau } 75510203ee5e3350758dae4bf9af05b1585029af7dWally Yau }; 76510203ee5e3350758dae4bf9af05b1585029af7dWally Yau 77510203ee5e3350758dae4bf9af05b1585029af7dWally Yau private BluetoothProfile.ServiceListener mServiceConnection = 78510203ee5e3350758dae4bf9af05b1585029af7dWally Yau new BluetoothProfile.ServiceListener() { 79510203ee5e3350758dae4bf9af05b1585029af7dWally Yau 80510203ee5e3350758dae4bf9af05b1585029af7dWally Yau @Override 81510203ee5e3350758dae4bf9af05b1585029af7dWally Yau public void onServiceDisconnected(int profile) { 82510203ee5e3350758dae4bf9af05b1585029af7dWally Yau Log.w(TAG, "Service disconnected, perhaps unexpectedly"); 83510203ee5e3350758dae4bf9af05b1585029af7dWally Yau unregisterConnectionStateReceiver(); 84510203ee5e3350758dae4bf9af05b1585029af7dWally Yau closeA2dpProfileProxy(); 85510203ee5e3350758dae4bf9af05b1585029af7dWally Yau mOpenConnectionCallback.failed(); 86510203ee5e3350758dae4bf9af05b1585029af7dWally Yau } 87510203ee5e3350758dae4bf9af05b1585029af7dWally Yau 88510203ee5e3350758dae4bf9af05b1585029af7dWally Yau @Override 89510203ee5e3350758dae4bf9af05b1585029af7dWally Yau public void onServiceConnected(int profile, BluetoothProfile proxy) { 90510203ee5e3350758dae4bf9af05b1585029af7dWally Yau if (DEBUG) { 91510203ee5e3350758dae4bf9af05b1585029af7dWally Yau Log.d(TAG, "Connection made to bluetooth proxy." ); 92510203ee5e3350758dae4bf9af05b1585029af7dWally Yau } 93510203ee5e3350758dae4bf9af05b1585029af7dWally Yau BluetoothA2dp mA2dpProfile = (BluetoothA2dp) proxy; 94510203ee5e3350758dae4bf9af05b1585029af7dWally Yau if (DEBUG) { 95510203ee5e3350758dae4bf9af05b1585029af7dWally Yau Log.d(TAG, "Connecting to target: " + mTarget.getAddress()); 96510203ee5e3350758dae4bf9af05b1585029af7dWally Yau } 97510203ee5e3350758dae4bf9af05b1585029af7dWally Yau 98510203ee5e3350758dae4bf9af05b1585029af7dWally Yau registerConnectionStateReceiver(); 99510203ee5e3350758dae4bf9af05b1585029af7dWally Yau 100510203ee5e3350758dae4bf9af05b1585029af7dWally Yau // TODO need to start a timer, otherwise if the connection fails we might be 101510203ee5e3350758dae4bf9af05b1585029af7dWally Yau // stuck here forever 102510203ee5e3350758dae4bf9af05b1585029af7dWally Yau mA2dpProfile.connect(mTarget); 103510203ee5e3350758dae4bf9af05b1585029af7dWally Yau 104510203ee5e3350758dae4bf9af05b1585029af7dWally Yau // must set PRIORITY_AUTO_CONNECT or auto-connection will not 105510203ee5e3350758dae4bf9af05b1585029af7dWally Yau // occur, however this setting does not appear to be sticky 106510203ee5e3350758dae4bf9af05b1585029af7dWally Yau // across a reboot 107510203ee5e3350758dae4bf9af05b1585029af7dWally Yau mA2dpProfile.setPriority(mTarget, BluetoothProfile.PRIORITY_AUTO_CONNECT); 108510203ee5e3350758dae4bf9af05b1585029af7dWally Yau } 109510203ee5e3350758dae4bf9af05b1585029af7dWally Yau }; 110510203ee5e3350758dae4bf9af05b1585029af7dWally Yau 111510203ee5e3350758dae4bf9af05b1585029af7dWally Yau private BluetoothA2dpConnector() { 112510203ee5e3350758dae4bf9af05b1585029af7dWally Yau } 113510203ee5e3350758dae4bf9af05b1585029af7dWally Yau 114510203ee5e3350758dae4bf9af05b1585029af7dWally Yau public BluetoothA2dpConnector(Context context, BluetoothDevice target, 115510203ee5e3350758dae4bf9af05b1585029af7dWally Yau BluetoothDevicePairer.OpenConnectionCallback callback) { 116510203ee5e3350758dae4bf9af05b1585029af7dWally Yau mContext = context; 117510203ee5e3350758dae4bf9af05b1585029af7dWally Yau mTarget = target; 118510203ee5e3350758dae4bf9af05b1585029af7dWally Yau mOpenConnectionCallback = callback; 119510203ee5e3350758dae4bf9af05b1585029af7dWally Yau } 120510203ee5e3350758dae4bf9af05b1585029af7dWally Yau 121510203ee5e3350758dae4bf9af05b1585029af7dWally Yau @Override 122510203ee5e3350758dae4bf9af05b1585029af7dWally Yau public void openConnection(BluetoothAdapter adapter) { 123510203ee5e3350758dae4bf9af05b1585029af7dWally Yau if (DEBUG) { 124510203ee5e3350758dae4bf9af05b1585029af7dWally Yau Log.d(TAG, "opening connection"); 125510203ee5e3350758dae4bf9af05b1585029af7dWally Yau } 126510203ee5e3350758dae4bf9af05b1585029af7dWally Yau if (!adapter.getProfileProxy(mContext, mServiceConnection, BluetoothProfile.A2DP)) { 127510203ee5e3350758dae4bf9af05b1585029af7dWally Yau mOpenConnectionCallback.failed(); 128510203ee5e3350758dae4bf9af05b1585029af7dWally Yau } 129510203ee5e3350758dae4bf9af05b1585029af7dWally Yau } 130510203ee5e3350758dae4bf9af05b1585029af7dWally Yau 131510203ee5e3350758dae4bf9af05b1585029af7dWally Yau private void closeA2dpProfileProxy() { 132510203ee5e3350758dae4bf9af05b1585029af7dWally Yau if (mA2dpProfile != null) { 133510203ee5e3350758dae4bf9af05b1585029af7dWally Yau try { 134510203ee5e3350758dae4bf9af05b1585029af7dWally Yau BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); 135510203ee5e3350758dae4bf9af05b1585029af7dWally Yau adapter.closeProfileProxy(BluetoothProfile.A2DP, mA2dpProfile); 136510203ee5e3350758dae4bf9af05b1585029af7dWally Yau mA2dpProfile = null; 137510203ee5e3350758dae4bf9af05b1585029af7dWally Yau } catch (Throwable t) { 138510203ee5e3350758dae4bf9af05b1585029af7dWally Yau Log.w(TAG, "Error cleaning up A2DP proxy", t); 139510203ee5e3350758dae4bf9af05b1585029af7dWally Yau } 140510203ee5e3350758dae4bf9af05b1585029af7dWally Yau } 141510203ee5e3350758dae4bf9af05b1585029af7dWally Yau } 142510203ee5e3350758dae4bf9af05b1585029af7dWally Yau 143510203ee5e3350758dae4bf9af05b1585029af7dWally Yau private void registerConnectionStateReceiver() { 144510203ee5e3350758dae4bf9af05b1585029af7dWally Yau if (DEBUG) Log.d(TAG, "registerConnectionStateReceiver()"); 145510203ee5e3350758dae4bf9af05b1585029af7dWally Yau IntentFilter filter = new IntentFilter(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED); 146510203ee5e3350758dae4bf9af05b1585029af7dWally Yau mContext.registerReceiver(mConnectionStateReceiver, filter); 147510203ee5e3350758dae4bf9af05b1585029af7dWally Yau mConnectionStateReceiverRegistered = true; 148510203ee5e3350758dae4bf9af05b1585029af7dWally Yau } 149510203ee5e3350758dae4bf9af05b1585029af7dWally Yau 150510203ee5e3350758dae4bf9af05b1585029af7dWally Yau private void unregisterConnectionStateReceiver() { 151510203ee5e3350758dae4bf9af05b1585029af7dWally Yau if (mConnectionStateReceiverRegistered) { 152510203ee5e3350758dae4bf9af05b1585029af7dWally Yau if (DEBUG) Log.d(TAG, "unregisterConnectionStateReceiver()"); 153510203ee5e3350758dae4bf9af05b1585029af7dWally Yau mContext.unregisterReceiver(mConnectionStateReceiver); 154510203ee5e3350758dae4bf9af05b1585029af7dWally Yau mConnectionStateReceiverRegistered = false; 155510203ee5e3350758dae4bf9af05b1585029af7dWally Yau } 156510203ee5e3350758dae4bf9af05b1585029af7dWally Yau } 157510203ee5e3350758dae4bf9af05b1585029af7dWally Yau 158510203ee5e3350758dae4bf9af05b1585029af7dWally Yau} 159