1 /* 2 * Copyright 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.car.settings.bluetooth; 18 19 import static android.os.UserManager.DISALLOW_CONFIG_BLUETOOTH; 20 21 import android.bluetooth.BluetoothDevice; 22 import android.car.drivingstate.CarUxRestrictions; 23 import android.content.Context; 24 25 import com.android.car.settings.R; 26 import com.android.car.settings.common.FragmentController; 27 import com.android.car.settings.common.Logger; 28 import com.android.internal.util.ArrayUtils; 29 import com.android.settingslib.bluetooth.BluetoothDeviceFilter; 30 import com.android.settingslib.bluetooth.BluetoothDeviceFilter.Filter; 31 import com.android.settingslib.bluetooth.CachedBluetoothDevice; 32 33 import java.util.Set; 34 35 /** 36 * Displays a list of unbonded (unpaired) Bluetooth devices. This controller also sets the 37 * Bluetooth adapter to discovery mode and begins scanning for discoverable devices for as long as 38 * the preference group is shown. Clicking on a device will start the pairing process. Discovery 39 * and scanning are halted while a device is pairing. Users with the {@link 40 * DISALLOW_CONFIG_BLUETOOTH} restriction cannot pair devices. 41 */ 42 public class BluetoothUnbondedDevicesPreferenceController extends 43 BluetoothScanningDevicesGroupPreferenceController { 44 45 private final Filter mUnbondedDeviceTypeFilter = new UnbondedDeviceTypeFilter(); 46 47 private static final Logger LOG = new Logger( 48 BluetoothUnbondedDevicesPreferenceController.class); 49 BluetoothUnbondedDevicesPreferenceController(Context context, String preferenceKey, FragmentController fragmentController, CarUxRestrictions uxRestrictions)50 public BluetoothUnbondedDevicesPreferenceController(Context context, String preferenceKey, 51 FragmentController fragmentController, CarUxRestrictions uxRestrictions) { 52 super(context, preferenceKey, fragmentController, uxRestrictions); 53 } 54 55 @Override getDeviceFilter()56 protected BluetoothDeviceFilter.Filter getDeviceFilter() { 57 return mUnbondedDeviceTypeFilter; 58 } 59 60 @Override onDeviceClickedInternal(CachedBluetoothDevice cachedDevice)61 protected void onDeviceClickedInternal(CachedBluetoothDevice cachedDevice) { 62 if (cachedDevice.startPairing()) { 63 LOG.d("startPairing"); 64 // Indicate that this client (vehicle) would like access to contacts (PBAP) and messages 65 // (MAP) if there is a server which permits it (usually a phone). 66 cachedDevice.getDevice().setPhonebookAccessPermission(BluetoothDevice.ACCESS_ALLOWED); 67 cachedDevice.getDevice().setMessageAccessPermission(BluetoothDevice.ACCESS_ALLOWED); 68 } else { 69 BluetoothUtils.showError(getContext(), cachedDevice.getName(), 70 R.string.bluetooth_pairing_error_message); 71 reenableScanning(); 72 } 73 } 74 75 @Override getAvailabilityStatus()76 protected int getAvailabilityStatus() { 77 int availabilityStatus = super.getAvailabilityStatus(); 78 if (availabilityStatus == AVAILABLE 79 && getUserManager().hasUserRestriction(DISALLOW_CONFIG_BLUETOOTH)) { 80 return DISABLED_FOR_PROFILE; 81 } 82 return availabilityStatus; 83 } 84 85 /** Filter that matches only unbonded devices with specific device types. */ 86 private class UnbondedDeviceTypeFilter implements Filter { 87 @Override matches(BluetoothDevice device)88 public boolean matches(BluetoothDevice device) { 89 int[] unbondedMajorClassFilter = getContext() 90 .getResources() 91 .getIntArray(R.array.config_unbonded_device_filter_allowlist); 92 //TODO(b/198339129): change to use device bond status 93 Set<BluetoothDevice> bondedDevices = mBluetoothAdapter.getBondedDevices(); 94 boolean matches = bondedDevices == null || !bondedDevices.contains(device); 95 if (matches && unbondedMajorClassFilter.length > 0) { 96 matches = device.getBluetoothClass() != null 97 && ArrayUtils.contains( 98 unbondedMajorClassFilter, 99 device.getBluetoothClass().getMajorDeviceClass()); 100 } 101 return matches; 102 } 103 } 104 } 105