1 /* 2 * Copyright (C) 2022 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.bluetooth; 18 19 import android.bluetooth.BluetoothProfile; 20 import android.content.Context; 21 import android.content.Intent; 22 import android.view.View; 23 import android.widget.Button; 24 import android.widget.LinearLayout; 25 import android.widget.TextView; 26 27 import androidx.preference.PreferenceCategory; 28 import androidx.preference.PreferenceScreen; 29 30 import com.android.settings.R; 31 import com.android.settingslib.bluetooth.BluetoothBroadcastUtils; 32 import com.android.settingslib.bluetooth.CachedBluetoothDevice; 33 import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcastAssistant; 34 import com.android.settingslib.bluetooth.LocalBluetoothManager; 35 import com.android.settingslib.core.lifecycle.Lifecycle; 36 import com.android.settingslib.widget.LayoutPreference; 37 38 /** 39 * This class adds a header to display the action button for joining the broadcast session 40 * by scanning QR code and leaving the broadcast session 41 */ 42 public class BluetoothFindBroadcastsHeaderController extends BluetoothDetailsController { 43 private static final String TAG = "BtFindBroadcastCtrl"; 44 45 private static final String KEY_BROADCAST_HEADER = "bluetooth_find_broadcast_header"; 46 private static final String KEY_BROADCAST_SOURCE_LIST = "broadcast_source_list"; 47 48 LayoutPreference mLayoutPreference; 49 PreferenceCategory mBroadcastSourceList; 50 TextView mTitle; 51 TextView mSummary; 52 Button mBtnFindBroadcast; 53 LinearLayout mBtnBroadcastLayout; 54 Button mBtnLeaveBroadcast; 55 Button mBtnScanQrCode; 56 BluetoothFindBroadcastsFragment mBluetoothFindBroadcastsFragment; BluetoothFindBroadcastsHeaderController(Context context, BluetoothFindBroadcastsFragment fragment, CachedBluetoothDevice device, Lifecycle lifecycle, LocalBluetoothManager bluetoothManager)57 public BluetoothFindBroadcastsHeaderController(Context context, 58 BluetoothFindBroadcastsFragment fragment, CachedBluetoothDevice device, 59 Lifecycle lifecycle, LocalBluetoothManager bluetoothManager) { 60 super(context, fragment, device, lifecycle); 61 mBluetoothFindBroadcastsFragment = fragment; 62 } 63 64 @Override init(PreferenceScreen screen)65 protected void init(PreferenceScreen screen) { 66 mLayoutPreference = screen.findPreference(KEY_BROADCAST_HEADER); 67 mBroadcastSourceList = screen.findPreference(KEY_BROADCAST_SOURCE_LIST); 68 69 refresh(); 70 } 71 72 @Override refresh()73 protected void refresh() { 74 if (mLayoutPreference == null || mCachedDevice == null) { 75 return; 76 } 77 78 mTitle = mLayoutPreference.findViewById(R.id.entity_header_title); 79 mTitle.setText(mCachedDevice.getName()); 80 mSummary = mLayoutPreference.findViewById(R.id.entity_header_summary); 81 mSummary.setText(""); 82 83 mBtnFindBroadcast = mLayoutPreference.findViewById(R.id.button_find_broadcast); 84 mBtnFindBroadcast.setOnClickListener(v -> scanBroadcastSource()); 85 mBtnBroadcastLayout = mLayoutPreference.findViewById(R.id.button_broadcast_layout); 86 mBtnLeaveBroadcast = mLayoutPreference.findViewById(R.id.button_leave_broadcast); 87 mBtnLeaveBroadcast.setOnClickListener(v -> leaveBroadcastSession()); 88 mBtnScanQrCode = mLayoutPreference.findViewById(R.id.button_scan_qr_code); 89 mBtnScanQrCode.setOnClickListener(v -> launchQrCodeScanner()); 90 91 updateHeaderLayout(); 92 } 93 isBroadcastSourceExist()94 private boolean isBroadcastSourceExist() { 95 return mBroadcastSourceList.getPreferenceCount() > 0; 96 } 97 updateHeaderLayout()98 private void updateHeaderLayout() { 99 if (isBroadcastSourceExist()) { 100 mBtnFindBroadcast.setVisibility(View.GONE); 101 mBtnBroadcastLayout.setVisibility(View.VISIBLE); 102 } else { 103 mBtnFindBroadcast.setVisibility(View.VISIBLE); 104 mBtnBroadcastLayout.setVisibility(View.GONE); 105 } 106 107 mBtnLeaveBroadcast.setEnabled(false); 108 if (mBluetoothFindBroadcastsFragment != null && mCachedDevice != null) { 109 LocalBluetoothLeBroadcastAssistant broadcastAssistant = 110 mBluetoothFindBroadcastsFragment.getLeBroadcastAssistant(); 111 if (broadcastAssistant != null 112 && broadcastAssistant.getConnectionStatus(mCachedDevice.getDevice()) 113 == BluetoothProfile.STATE_CONNECTED) { 114 mBtnLeaveBroadcast.setEnabled(true); 115 } 116 } 117 } 118 scanBroadcastSource()119 private void scanBroadcastSource() { 120 // TODO(b/231543455) : Using the BluetoothDeviceUpdater to refactor it. 121 if (mBluetoothFindBroadcastsFragment == null) { 122 return; 123 } 124 mBluetoothFindBroadcastsFragment.scanBroadcastSource(); 125 } 126 leaveBroadcastSession()127 private void leaveBroadcastSession() { 128 if (mBluetoothFindBroadcastsFragment == null) { 129 return; 130 } 131 mBluetoothFindBroadcastsFragment.leaveBroadcastSession(); 132 } 133 launchQrCodeScanner()134 private void launchQrCodeScanner() { 135 final Intent intent = new Intent(mContext, QrCodeScanModeActivity.class); 136 intent.setAction(BluetoothBroadcastUtils.ACTION_BLUETOOTH_LE_AUDIO_QR_CODE_SCANNER) 137 .putExtra(BluetoothBroadcastUtils.EXTRA_BLUETOOTH_SINK_IS_GROUP, true) 138 .putExtra(BluetoothBroadcastUtils.EXTRA_BLUETOOTH_DEVICE_SINK, 139 mCachedDevice.getDevice()); 140 mBluetoothFindBroadcastsFragment.startActivityForResult(intent, 141 BluetoothFindBroadcastsFragment.REQUEST_SCAN_BT_BROADCAST_QR_CODE); 142 } 143 144 @Override onDeviceAttributesChanged()145 public void onDeviceAttributesChanged() { 146 if (mCachedDevice != null) { 147 refresh(); 148 } 149 } 150 151 @Override getPreferenceKey()152 public String getPreferenceKey() { 153 return KEY_BROADCAST_HEADER; 154 } 155 156 /** 157 * Updates the UI 158 */ refreshUi()159 public void refreshUi() { 160 updateHeaderLayout(); 161 } 162 } 163