1 /* 2 * Copyright (C) 2017 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.car.settings.bluetooth; 18 19 import static android.os.UserManager.DISALLOW_BLUETOOTH; 20 21 import android.bluetooth.BluetoothAdapter; 22 import android.content.BroadcastReceiver; 23 import android.content.Context; 24 import android.content.Intent; 25 import android.content.IntentFilter; 26 import android.os.Bundle; 27 import android.os.UserManager; 28 import android.provider.Settings; 29 30 import androidx.annotation.XmlRes; 31 32 import com.android.car.settings.R; 33 import com.android.car.settings.common.SettingsFragment; 34 import com.android.car.settings.search.CarBaseSearchIndexProvider; 35 import com.android.car.ui.toolbar.MenuItem; 36 import com.android.settingslib.bluetooth.LocalBluetoothManager; 37 import com.android.settingslib.search.SearchIndexable; 38 39 import java.util.Collections; 40 import java.util.List; 41 42 /** 43 * Main page for Bluetooth settings. It manages the power switch for the Bluetooth adapter. It also 44 * displays paired devices and the entry point for device pairing. 45 */ 46 @SearchIndexable 47 public class BluetoothSettingsFragment extends SettingsFragment { 48 49 private final BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); 50 private final IntentFilter mIntentFilter = new IntentFilter( 51 BluetoothAdapter.ACTION_STATE_CHANGED); 52 private final BroadcastReceiver mReceiver = new BroadcastReceiver() { 53 @Override 54 public void onReceive(Context context, Intent intent) { 55 int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR); 56 handleStateChanged(state); 57 } 58 }; 59 private final MenuItem.OnClickListener mBluetoothSwitchListener = item -> { 60 item.setEnabled(false); 61 if (item.isChecked()) { 62 mBluetoothAdapter.enable(); 63 } else { 64 mBluetoothAdapter.disable(); 65 } 66 }; 67 68 private UserManager mUserManager; 69 private LocalBluetoothManager mLocalBluetoothManager; 70 private MenuItem mBluetoothSwitch; 71 72 @Override 73 @XmlRes getPreferenceScreenResId()74 protected int getPreferenceScreenResId() { 75 return R.xml.bluetooth_settings_fragment; 76 } 77 78 @Override getToolbarMenuItems()79 protected List<MenuItem> getToolbarMenuItems() { 80 return Collections.singletonList(mBluetoothSwitch); 81 } 82 83 @Override onCreate(Bundle savedInstanceState)84 public void onCreate(Bundle savedInstanceState) { 85 super.onCreate(savedInstanceState); 86 87 mBluetoothSwitch = new MenuItem.Builder(getContext()) 88 .setCheckable() 89 .setOnClickListener(mBluetoothSwitchListener) 90 .build(); 91 } 92 93 @Override onAttach(Context context)94 public void onAttach(Context context) { 95 super.onAttach(context); 96 mUserManager = UserManager.get(context); 97 mLocalBluetoothManager = BluetoothUtils.getLocalBtManager(context); 98 if (mLocalBluetoothManager == null) { 99 goBack(); 100 } 101 } 102 103 @Override onStart()104 public void onStart() { 105 super.onStart(); 106 requireContext().registerReceiver(mReceiver, mIntentFilter); 107 mLocalBluetoothManager.setForegroundActivity(requireActivity()); 108 handleStateChanged(mBluetoothAdapter.getState()); 109 } 110 111 @Override onStop()112 public void onStop() { 113 super.onStop(); 114 requireContext().unregisterReceiver(mReceiver); 115 mLocalBluetoothManager.setForegroundActivity(null); 116 } 117 isUserRestricted()118 private boolean isUserRestricted() { 119 return mUserManager.hasUserRestriction(DISALLOW_BLUETOOTH); 120 } 121 handleStateChanged(int state)122 private void handleStateChanged(int state) { 123 // Momentarily clear the listener so that we don't update the adapter while trying to 124 // reflect the adapter state. 125 mBluetoothSwitch.setOnClickListener(null); 126 switch (state) { 127 case BluetoothAdapter.STATE_TURNING_ON: 128 mBluetoothSwitch.setEnabled(false); 129 mBluetoothSwitch.setChecked(true); 130 break; 131 case BluetoothAdapter.STATE_ON: 132 mBluetoothSwitch.setEnabled(!isUserRestricted()); 133 mBluetoothSwitch.setChecked(true); 134 break; 135 case BluetoothAdapter.STATE_TURNING_OFF: 136 mBluetoothSwitch.setEnabled(false); 137 mBluetoothSwitch.setChecked(false); 138 break; 139 case BluetoothAdapter.STATE_OFF: 140 default: 141 mBluetoothSwitch.setEnabled(!isUserRestricted()); 142 mBluetoothSwitch.setChecked(false); 143 } 144 mBluetoothSwitch.setOnClickListener(mBluetoothSwitchListener); 145 } 146 147 public static final CarBaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = 148 new CarBaseSearchIndexProvider(R.xml.bluetooth_settings_fragment, 149 Settings.ACTION_BLUETOOTH_SETTINGS); 150 } 151