The Settings app offers several Bluetooth intents, and they need to be updated to enforce the new "Nearby devices" runtime permission model, since the old BLUETOOTH and BLUETOOTH_ADMIN permissions have been deprecated. Bug: 191174082 Test: TH Change-Id: I0d812f486bc3dadc517d5b04d3082d4f56f60ef4
218 lines
7.1 KiB
Java
218 lines
7.1 KiB
Java
/*
|
|
* Copyright (C) 2011 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
package com.android.settings.bluetooth;
|
|
|
|
import static android.os.UserManager.DISALLOW_CONFIG_BLUETOOTH;
|
|
|
|
import android.Manifest;
|
|
import android.app.settings.SettingsEnums;
|
|
import android.bluetooth.BluetoothAdapter;
|
|
import android.bluetooth.BluetoothDevice;
|
|
import android.bluetooth.BluetoothDevicePicker;
|
|
import android.content.Context;
|
|
import android.content.Intent;
|
|
import android.os.Bundle;
|
|
import android.os.UserManager;
|
|
import android.util.Log;
|
|
import android.text.TextUtils;
|
|
import android.view.Menu;
|
|
import android.view.MenuInflater;
|
|
|
|
import androidx.annotation.VisibleForTesting;
|
|
|
|
import com.android.settings.R;
|
|
import com.android.settings.password.PasswordUtils;
|
|
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
|
import com.android.settingslib.core.AbstractPreferenceController;
|
|
|
|
import java.util.List;
|
|
|
|
/**
|
|
* BluetoothSettings is the Settings screen for Bluetooth configuration and
|
|
* connection management.
|
|
*/
|
|
public final class DevicePickerFragment extends DeviceListPreferenceFragment {
|
|
private static final String KEY_BT_DEVICE_LIST = "bt_device_list";
|
|
private static final String TAG = "DevicePickerFragment";
|
|
|
|
@VisibleForTesting
|
|
BluetoothProgressCategory mAvailableDevicesCategory;
|
|
@VisibleForTesting
|
|
Context mContext;
|
|
@VisibleForTesting
|
|
String mLaunchPackage;
|
|
@VisibleForTesting
|
|
String mLaunchClass;
|
|
@VisibleForTesting
|
|
String mCallingAppPackageName;
|
|
|
|
private boolean mNeedAuth;
|
|
private boolean mScanAllowed;
|
|
|
|
public DevicePickerFragment() {
|
|
super(null /* Not tied to any user restrictions. */);
|
|
}
|
|
|
|
@Override
|
|
void initPreferencesFromPreferenceScreen() {
|
|
Intent intent = getActivity().getIntent();
|
|
mNeedAuth = intent.getBooleanExtra(BluetoothDevicePicker.EXTRA_NEED_AUTH, false);
|
|
setFilter(intent.getIntExtra(BluetoothDevicePicker.EXTRA_FILTER_TYPE,
|
|
BluetoothDevicePicker.FILTER_TYPE_ALL));
|
|
mLaunchPackage = intent.getStringExtra(BluetoothDevicePicker.EXTRA_LAUNCH_PACKAGE);
|
|
mLaunchClass = intent.getStringExtra(BluetoothDevicePicker.EXTRA_LAUNCH_CLASS);
|
|
mAvailableDevicesCategory = (BluetoothProgressCategory) findPreference(KEY_BT_DEVICE_LIST);
|
|
}
|
|
|
|
@Override
|
|
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
|
super.onCreateOptionsMenu(menu, inflater);
|
|
}
|
|
|
|
@Override
|
|
public int getMetricsCategory() {
|
|
return SettingsEnums.BLUETOOTH_DEVICE_PICKER;
|
|
}
|
|
|
|
@Override
|
|
public void onCreate(Bundle savedInstanceState) {
|
|
super.onCreate(savedInstanceState);
|
|
getActivity().setTitle(getString(R.string.device_picker));
|
|
UserManager um = (UserManager) getSystemService(Context.USER_SERVICE);
|
|
mScanAllowed = !um.hasUserRestriction(DISALLOW_CONFIG_BLUETOOTH);
|
|
mCallingAppPackageName = PasswordUtils.getCallingAppPackageName(
|
|
getActivity().getActivityToken());
|
|
if (!TextUtils.equals(mCallingAppPackageName, mLaunchPackage)) {
|
|
Log.w(TAG, "sendDevicePickedIntent() launch package name is not equivalent to"
|
|
+ " calling package name!");
|
|
}
|
|
mContext = getContext();
|
|
setHasOptionsMenu(true);
|
|
}
|
|
|
|
@Override
|
|
public void onStart() {
|
|
super.onStart();
|
|
addCachedDevices();
|
|
mSelectedDevice = null;
|
|
if (mScanAllowed) {
|
|
enableScanning();
|
|
mAvailableDevicesCategory.setProgress(mBluetoothAdapter.isDiscovering());
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void onStop() {
|
|
// Try disable scanning no matter what, no effect if enableScanning has not been called
|
|
disableScanning();
|
|
super.onStop();
|
|
}
|
|
|
|
@Override
|
|
public void onDestroy() {
|
|
super.onDestroy();
|
|
/* Check if any device was selected, if no device selected
|
|
* send ACTION_DEVICE_SELECTED with a null device, otherwise
|
|
* don't do anything */
|
|
if (mSelectedDevice == null) {
|
|
sendDevicePickedIntent(null);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
void onDevicePreferenceClick(BluetoothDevicePreference btPreference) {
|
|
disableScanning();
|
|
LocalBluetoothPreferences.persistSelectedDeviceInPicker(
|
|
getActivity(), mSelectedDevice.getAddress());
|
|
if ((btPreference.getCachedDevice().getBondState() ==
|
|
BluetoothDevice.BOND_BONDED) || !mNeedAuth) {
|
|
sendDevicePickedIntent(mSelectedDevice);
|
|
finish();
|
|
} else {
|
|
super.onDevicePreferenceClick(btPreference);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void onScanningStateChanged(boolean started) {
|
|
super.onScanningStateChanged(started);
|
|
started |= mScanEnabled;
|
|
mAvailableDevicesCategory.setProgress(started);
|
|
}
|
|
|
|
public void onDeviceBondStateChanged(CachedBluetoothDevice cachedDevice,
|
|
int bondState) {
|
|
BluetoothDevice device = cachedDevice.getDevice();
|
|
if (!device.equals(mSelectedDevice)) {
|
|
return;
|
|
}
|
|
if (bondState == BluetoothDevice.BOND_BONDED) {
|
|
sendDevicePickedIntent(device);
|
|
finish();
|
|
} else if (bondState == BluetoothDevice.BOND_NONE) {
|
|
enableScanning();
|
|
}
|
|
}
|
|
|
|
@Override
|
|
protected void initDevicePreference(BluetoothDevicePreference preference) {
|
|
super.initDevicePreference(preference);
|
|
preference.setNeedNotifyHierarchyChanged(true);
|
|
}
|
|
|
|
@Override
|
|
public void onBluetoothStateChanged(int bluetoothState) {
|
|
super.onBluetoothStateChanged(bluetoothState);
|
|
|
|
if (bluetoothState == BluetoothAdapter.STATE_ON) {
|
|
enableScanning();
|
|
}
|
|
}
|
|
|
|
@Override
|
|
protected String getLogTag() {
|
|
return TAG;
|
|
}
|
|
|
|
@Override
|
|
protected int getPreferenceScreenResId() {
|
|
return R.xml.device_picker;
|
|
}
|
|
|
|
@Override
|
|
protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
|
|
return null;
|
|
}
|
|
|
|
@Override
|
|
public String getDeviceListKey() {
|
|
return KEY_BT_DEVICE_LIST;
|
|
}
|
|
|
|
private void sendDevicePickedIntent(BluetoothDevice device) {
|
|
Intent intent = new Intent(BluetoothDevicePicker.ACTION_DEVICE_SELECTED);
|
|
intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
|
|
if (mLaunchPackage != null && mLaunchClass != null) {
|
|
if (TextUtils.equals(mCallingAppPackageName, mLaunchPackage)) {
|
|
intent.setClassName(mLaunchPackage, mLaunchClass);
|
|
}
|
|
}
|
|
|
|
mContext.sendBroadcast(intent, Manifest.permission.BLUETOOTH_CONNECT);
|
|
}
|
|
}
|