• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License
15  */
16 
17 package com.android.server.telecom.bluetooth;
18 
19 import android.bluetooth.BluetoothDevice;
20 import android.bluetooth.BluetoothHeadset;
21 import android.content.BroadcastReceiver;
22 import android.content.Context;
23 import android.content.Intent;
24 import android.content.IntentFilter;
25 import android.telecom.Log;
26 import android.telecom.Logging.Session;
27 
28 import com.android.internal.os.SomeArgs;
29 
30 import static com.android.server.telecom.bluetooth.BluetoothRouteManager.HFP_IS_ON;
31 import static com.android.server.telecom.bluetooth.BluetoothRouteManager.HFP_LOST;
32 
33 
34 public class BluetoothStateReceiver extends BroadcastReceiver {
35     private static final String LOG_TAG = BluetoothStateReceiver.class.getSimpleName();
36     public static final IntentFilter INTENT_FILTER;
37     static {
38         INTENT_FILTER = new IntentFilter();
39         INTENT_FILTER.addAction(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED);
40         INTENT_FILTER.addAction(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED);
41         INTENT_FILTER.addAction(BluetoothHeadset.ACTION_ACTIVE_DEVICE_CHANGED);
42     }
43 
44     // If not in a call, BSR won't listen to the Bluetooth stack's HFP on/off messages, since
45     // other apps could be turning it on and off. We don't want to interfere.
46     private boolean mIsInCall = false;
47     private final BluetoothRouteManager mBluetoothRouteManager;
48     private final BluetoothDeviceManager mBluetoothDeviceManager;
49 
onReceive(Context context, Intent intent)50     public void onReceive(Context context, Intent intent) {
51         Log.startSession("BSR.oR");
52         try {
53             String action = intent.getAction();
54             switch (action) {
55                 case BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED:
56                     handleAudioStateChanged(intent);
57                     break;
58                 case BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED:
59                     handleConnectionStateChanged(intent);
60                     break;
61                 case BluetoothHeadset.ACTION_ACTIVE_DEVICE_CHANGED:
62                     handleActiveDeviceChanged(intent);
63                     break;
64             }
65         } finally {
66             Log.endSession();
67         }
68     }
69 
handleAudioStateChanged(Intent intent)70     private void handleAudioStateChanged(Intent intent) {
71         if (!mIsInCall) {
72             Log.i(LOG_TAG, "Ignoring BT audio state change since we're not in a call");
73             return;
74         }
75         int bluetoothHeadsetAudioState =
76                 intent.getIntExtra(BluetoothHeadset.EXTRA_STATE,
77                         BluetoothHeadset.STATE_AUDIO_DISCONNECTED);
78         BluetoothDevice device =
79                 intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
80         if (device == null) {
81             Log.w(LOG_TAG, "Got null device from broadcast. " +
82                     "Ignoring.");
83             return;
84         }
85 
86         Log.i(LOG_TAG, "Device %s transitioned to audio state %d",
87                 device.getAddress(), bluetoothHeadsetAudioState);
88         Session session = Log.createSubsession();
89         SomeArgs args = SomeArgs.obtain();
90         args.arg1 = session;
91         args.arg2 = device.getAddress();
92         switch (bluetoothHeadsetAudioState) {
93             case BluetoothHeadset.STATE_AUDIO_CONNECTED:
94                 mBluetoothRouteManager.sendMessage(HFP_IS_ON, args);
95                 break;
96             case BluetoothHeadset.STATE_AUDIO_DISCONNECTED:
97                 mBluetoothRouteManager.sendMessage(HFP_LOST, args);
98                 break;
99         }
100     }
101 
handleConnectionStateChanged(Intent intent)102     private void handleConnectionStateChanged(Intent intent) {
103         int bluetoothHeadsetState = intent.getIntExtra(BluetoothHeadset.EXTRA_STATE,
104                 BluetoothHeadset.STATE_DISCONNECTED);
105         BluetoothDevice device =
106                 intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
107 
108         if (device == null) {
109             Log.w(LOG_TAG, "Got null device from broadcast. " +
110                     "Ignoring.");
111             return;
112         }
113 
114         Log.i(LOG_TAG, "Device %s changed state to %d",
115                 device.getAddress(), bluetoothHeadsetState);
116 
117         if (bluetoothHeadsetState == BluetoothHeadset.STATE_CONNECTED) {
118             mBluetoothDeviceManager.onDeviceConnected(device);
119         } else if (bluetoothHeadsetState == BluetoothHeadset.STATE_DISCONNECTED
120                 || bluetoothHeadsetState == BluetoothHeadset.STATE_DISCONNECTING) {
121             mBluetoothDeviceManager.onDeviceDisconnected(device);
122         }
123     }
124 
handleActiveDeviceChanged(Intent intent)125     private void handleActiveDeviceChanged(Intent intent) {
126         BluetoothDevice device =
127                 intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
128         Log.i(LOG_TAG, "Device %s is now the preferred HFP device", device);
129         mBluetoothRouteManager.onActiveDeviceChanged(device);
130     }
131 
BluetoothStateReceiver(BluetoothDeviceManager deviceManager, BluetoothRouteManager routeManager)132     public BluetoothStateReceiver(BluetoothDeviceManager deviceManager,
133             BluetoothRouteManager routeManager) {
134         mBluetoothDeviceManager = deviceManager;
135         mBluetoothRouteManager = routeManager;
136     }
137 
setIsInCall(boolean isInCall)138     public void setIsInCall(boolean isInCall) {
139         mIsInCall = isInCall;
140     }
141 }
142