1 /* 2 * Copyright (C) 2023 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.media; 18 19 import android.annotation.NonNull; 20 import android.annotation.Nullable; 21 import android.bluetooth.BluetoothAdapter; 22 import android.bluetooth.BluetoothManager; 23 import android.content.Context; 24 import android.media.MediaRoute2Info; 25 import android.os.UserHandle; 26 27 import com.android.media.flags.Flags; 28 29 import java.util.Collections; 30 import java.util.List; 31 import java.util.Objects; 32 33 /** 34 * Provides control over bluetooth routes. 35 */ 36 /* package */ interface BluetoothRouteController { 37 38 /** 39 * Returns a new instance of {@link LegacyBluetoothRouteController}. 40 * 41 * <p>It may return {@link NoOpBluetoothRouteController} if Bluetooth is not supported on this 42 * hardware platform. 43 */ 44 @NonNull createInstance(@onNull Context context, @NonNull BluetoothRouteController.BluetoothRoutesUpdatedListener listener)45 static BluetoothRouteController createInstance(@NonNull Context context, 46 @NonNull BluetoothRouteController.BluetoothRoutesUpdatedListener listener) { 47 Objects.requireNonNull(listener); 48 BluetoothAdapter btAdapter = context.getSystemService(BluetoothManager.class).getAdapter(); 49 50 if (btAdapter == null || Flags.enableAudioPoliciesDeviceAndBluetoothController()) { 51 return new NoOpBluetoothRouteController(); 52 } else { 53 return new LegacyBluetoothRouteController(context, btAdapter, listener); 54 } 55 } 56 57 /** 58 * Makes the controller to listen to events from Bluetooth stack. 59 * 60 * @param userHandle is needed to subscribe for broadcasts on user's behalf. 61 */ start(@onNull UserHandle userHandle)62 void start(@NonNull UserHandle userHandle); 63 64 /** 65 * Stops the controller from listening to any Bluetooth events. 66 */ stop()67 void stop(); 68 69 /** 70 * Transfers Bluetooth output to the given route. 71 * 72 * <p>If the route is {@code null} then active route will be deactivated. 73 * 74 * @param routeId to switch to or {@code null} to unset the active device. 75 */ transferTo(@ullable String routeId)76 void transferTo(@Nullable String routeId); 77 78 /** 79 * Returns currently selected Bluetooth route. 80 * 81 * @return the selected route or {@code null} if there are no active routes. 82 */ 83 @Nullable getSelectedRoute()84 MediaRoute2Info getSelectedRoute(); 85 86 /** 87 * Returns transferable routes. 88 * 89 * <p>A route is considered to be transferable if the bluetooth device is connected but not 90 * considered as selected. 91 * 92 * @return list of transferable routes or an empty list. 93 */ 94 @NonNull getTransferableRoutes()95 List<MediaRoute2Info> getTransferableRoutes(); 96 97 /** 98 * Provides all connected Bluetooth routes. 99 * 100 * @return list of Bluetooth routes or an empty list. 101 */ 102 @NonNull getAllBluetoothRoutes()103 List<MediaRoute2Info> getAllBluetoothRoutes(); 104 105 /** 106 * Updates the volume for all Bluetooth devices for the given profile. 107 * 108 * @param devices specifies the profile, may be, {@link android.bluetooth.BluetoothA2dp}, {@link 109 * android.bluetooth.BluetoothLeAudio}, or {@link android.bluetooth.BluetoothHearingAid} 110 * @param volume the specific volume value for the given devices or 0 if unknown. 111 * @return {@code true} if updated successfully and {@code false} otherwise. 112 */ updateVolumeForDevices(int devices, int volume)113 boolean updateVolumeForDevices(int devices, int volume); 114 115 /** 116 * Interface for receiving events about Bluetooth routes changes. 117 */ 118 interface BluetoothRoutesUpdatedListener { 119 120 /** Called when Bluetooth routes have changed. */ onBluetoothRoutesUpdated()121 void onBluetoothRoutesUpdated(); 122 } 123 124 /** 125 * No-op implementation of {@link BluetoothRouteController}. 126 * 127 * <p>Useful if the device does not support Bluetooth. 128 */ 129 class NoOpBluetoothRouteController implements BluetoothRouteController { 130 131 @Override start(UserHandle userHandle)132 public void start(UserHandle userHandle) { 133 // no op 134 } 135 136 @Override stop()137 public void stop() { 138 // no op 139 } 140 141 @Override transferTo(String routeId)142 public void transferTo(String routeId) { 143 // no op 144 } 145 146 @Override getSelectedRoute()147 public MediaRoute2Info getSelectedRoute() { 148 // no op 149 return null; 150 } 151 152 @Override getTransferableRoutes()153 public List<MediaRoute2Info> getTransferableRoutes() { 154 // no op 155 return Collections.emptyList(); 156 } 157 158 @Override getAllBluetoothRoutes()159 public List<MediaRoute2Info> getAllBluetoothRoutes() { 160 // no op 161 return Collections.emptyList(); 162 } 163 164 @Override updateVolumeForDevices(int devices, int volume)165 public boolean updateVolumeForDevices(int devices, int volume) { 166 // no op 167 return false; 168 } 169 } 170 } 171