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.settings.sound; 18 19 import android.bluetooth.BluetoothDevice; 20 import android.content.Context; 21 import android.content.Intent; 22 import android.media.AudioManager; 23 import android.media.session.MediaController; 24 import android.media.session.MediaSessionManager; 25 import android.text.TextUtils; 26 27 import androidx.preference.Preference; 28 import androidx.preference.PreferenceScreen; 29 30 import com.android.settings.R; 31 import com.android.settings.media.MediaOutputUtils; 32 import com.android.settingslib.Utils; 33 import com.android.settingslib.bluetooth.A2dpProfile; 34 import com.android.settingslib.bluetooth.HearingAidProfile; 35 import com.android.settingslib.media.MediaOutputConstants; 36 37 import java.util.List; 38 39 /** 40 * This class allows launching MediaOutputDialog to switch output device. 41 * Preference would hide only when 42 * - Bluetooth = OFF 43 * - Bluetooth = ON and Connected Devices = 0 and Previously Connected = 0 44 * - Media stream captured by remote device 45 * - During a call. 46 */ 47 public class MediaOutputPreferenceController extends AudioSwitchPreferenceController { 48 49 private MediaController mMediaController; 50 MediaOutputPreferenceController(Context context, String key)51 public MediaOutputPreferenceController(Context context, String key) { 52 super(context, key); 53 mMediaController = MediaOutputUtils.getActiveLocalMediaController(context.getSystemService( 54 MediaSessionManager.class)); 55 } 56 57 @Override displayPreference(PreferenceScreen screen)58 public void displayPreference(PreferenceScreen screen) { 59 super.displayPreference(screen); 60 61 if (!Utils.isAudioModeOngoingCall(mContext) && mMediaController != null) { 62 mPreference.setVisible(true); 63 } 64 } 65 66 @Override updateState(Preference preference)67 public void updateState(Preference preference) { 68 if (preference == null) { 69 // In case UI is not ready. 70 return; 71 } 72 73 if (mMediaController == null) { 74 // No active local playback 75 return; 76 } 77 78 if (Utils.isAudioModeOngoingCall(mContext)) { 79 // Ongoing call status, switch entry for media will be disabled. 80 mPreference.setVisible(false); 81 preference.setSummary( 82 mContext.getText(R.string.media_out_summary_ongoing_call_state)); 83 return; 84 } 85 86 BluetoothDevice activeDevice = null; 87 // Show preference if there is connected or previously connected device 88 // Find active device and set its name as the preference's summary 89 List<BluetoothDevice> connectedA2dpDevices = getConnectedA2dpDevices(); 90 List<BluetoothDevice> connectedHADevices = getConnectedHearingAidDevices(); 91 if (mAudioManager.getMode() == AudioManager.MODE_NORMAL 92 && ((connectedA2dpDevices != null && !connectedA2dpDevices.isEmpty()) 93 || (connectedHADevices != null && !connectedHADevices.isEmpty()))) { 94 activeDevice = findActiveDevice(); 95 } 96 mPreference.setTitle(mContext.getString(R.string.media_output_label_title, 97 com.android.settings.Utils.getApplicationLabel(mContext, 98 mMediaController.getPackageName()))); 99 mPreference.setSummary((activeDevice == null) ? 100 mContext.getText(R.string.media_output_default_summary) : 101 activeDevice.getAlias()); 102 } 103 104 @Override findActiveDevice()105 public BluetoothDevice findActiveDevice() { 106 BluetoothDevice activeDevice = findActiveHearingAidDevice(); 107 final A2dpProfile a2dpProfile = mProfileManager.getA2dpProfile(); 108 109 if (activeDevice == null && a2dpProfile != null) { 110 activeDevice = a2dpProfile.getActiveDevice(); 111 } 112 return activeDevice; 113 } 114 115 /** 116 * Find active hearing aid device 117 */ 118 @Override findActiveHearingAidDevice()119 protected BluetoothDevice findActiveHearingAidDevice() { 120 final HearingAidProfile hearingAidProfile = mProfileManager.getHearingAidProfile(); 121 122 if (hearingAidProfile != null) { 123 List<BluetoothDevice> activeDevices = hearingAidProfile.getActiveDevices(); 124 for (BluetoothDevice btDevice : activeDevices) { 125 if (btDevice != null) { 126 return btDevice; 127 } 128 } 129 } 130 return null; 131 } 132 133 @Override handlePreferenceTreeClick(Preference preference)134 public boolean handlePreferenceTreeClick(Preference preference) { 135 if (TextUtils.equals(preference.getKey(), getPreferenceKey())) { 136 mContext.sendBroadcast(new Intent() 137 .setAction(MediaOutputConstants.ACTION_LAUNCH_MEDIA_OUTPUT_DIALOG) 138 .setPackage(MediaOutputConstants.SYSTEMUI_PACKAGE_NAME) 139 .putExtra(MediaOutputConstants.EXTRA_PACKAGE_NAME, 140 mMediaController.getPackageName()) 141 .putExtra(MediaOutputConstants.KEY_MEDIA_SESSION_TOKEN, 142 mMediaController.getSessionToken())); 143 return true; 144 } 145 return false; 146 } 147 } 148