blob: 6baa20a687a103d84591fb9bb9e55f4fd5939c01 [file] [log] [blame]
/*
* Copyright (C) 2017 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 android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BleBroadcastSourceInfo;
import android.content.Context;
import java.util.Iterator;
import android.os.Bundle;
import android.util.Log;
import androidx.preference.Preference;
import com.android.settings.R;
import com.android.settings.connecteddevice.DevicePreferenceCallback;
import com.android.settings.core.SubSettingLauncher;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.widget.GearPreference;
import com.android.settingslib.bluetooth.BluetoothCallback;
import com.android.settingslib.bluetooth.BluetoothDeviceFilter;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import com.android.settingslib.bluetooth.VendorCachedBluetoothDevice;
import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.lang.Integer;
/**
* Update the Ble broadcast source Info preference entries. It retrieves the Bluetooth broadcast source
* information using CachedBluetoothDevice object from setting library
* {@link BluetoothCallback}. It notifies the upper level whether to add/remove the preference
* through {@link BleBroadcastSourceInfoPreferenceCallback}
*
* In {@link BleBroadcastSourceInfoUpdater}, it uses {@link BluetoothDeviceFilter.Filter} to detect
* whether the {@link CachedBluetoothDevice} is relevant.
*/
public abstract class BleBroadcastSourceInfoUpdater implements CachedBluetoothDevice.Callback,
BluetoothCallback {
private static final String TAG = "BleBroadcastSourceInfoUpdater";
private static final boolean DBG = false;
protected final BleBroadcastSourceInfoPreferenceCallback mBleSourceInfoPreferenceCallback;
protected final Map<Integer, Preference> mPreferenceMap;
protected Context mPrefContext;
protected DashboardFragment mFragment;
protected final CachedBluetoothDevice mCachedDevice;
protected final VendorCachedBluetoothDevice mVendorCachedDevice;
private LocalBluetoothManager mLocalManager;
final GearPreference.OnGearClickListener mSourceInfoEntryListener = pref -> {
launchSourceInfoDetails(pref);
};
public BleBroadcastSourceInfoUpdater(Context context, DashboardFragment fragment,
BleBroadcastSourceInfoPreferenceCallback aBleSourceInfoPreferenceCallback,
CachedBluetoothDevice device) {
this(fragment, aBleSourceInfoPreferenceCallback ,device);
}
BleBroadcastSourceInfoUpdater(DashboardFragment fragment,
BleBroadcastSourceInfoPreferenceCallback aBleSourceInfoPreferenceCallback,
CachedBluetoothDevice device) {
mCachedDevice = device;
LocalBluetoothManager mgr = Utils.getLocalBtManager(mPrefContext);
LocalBluetoothProfileManager profileManager = mgr.getProfileManager();
mVendorCachedDevice = VendorCachedBluetoothDevice.getVendorCachedBluetoothDevice(device, profileManager);
mFragment = fragment;
mBleSourceInfoPreferenceCallback = aBleSourceInfoPreferenceCallback;
mPreferenceMap = new HashMap<Integer, Preference>();
mLocalManager = Utils.getLocalBtManager(mPrefContext);
mLocalManager.getEventManager().registerCallback(this);
}
/**
* Register the bluetooth event callback and update the list
*/
public void registerCallback() {
mCachedDevice.registerCallback(this);
forceUpdate();
}
/**
* Unregister the bluetooth event callback
*/
public void unregisterCallback() {
mCachedDevice.unregisterCallback(this);
}
@Override
public void onBluetoothStateChanged(int bluetoothState) {
BroadcastScanAssistanceUtils.debug(TAG, "onBluetoothStateChanged");
if (bluetoothState == BluetoothAdapter.STATE_OFF) {
removeAllBleBroadcastSourceInfosFromPreference();
}
//forceUpdate();
}
/**
* Force to update the list of bluetooth devices
*/
public void forceUpdate() {
if (mCachedDevice != null &&
mVendorCachedDevice.getNumberOfBleBroadcastReceiverStates() > 0) {
final Map<Integer, BleBroadcastSourceInfo> srcInfos =
mVendorCachedDevice.getAllBleBroadcastreceiverStates();
if (srcInfos == null) {
Log.e(TAG, "srcInfos is null");
return;
}
for (Map.Entry<Integer, BleBroadcastSourceInfo> entry: srcInfos.entrySet()) {
update(entry.getKey(), entry.getValue());
}
} else {
BroadcastScanAssistanceUtils.debug(TAG, "remove all the preferences as there are no rcvr states");
removeAllBleBroadcastSourceInfosFromPreference();
}
}
public void removeAllBleBroadcastSourceInfosFromPreference() {
Iterator<Map.Entry<Integer, Preference>> entries = mPreferenceMap.entrySet().iterator();
while (entries.hasNext()) {
//for (Map.Entry<Integer, Preference> entry: mPreferenceMap.entrySet()) {
Map.Entry<Integer, Preference> entry = entries.next();
//removePreference(entry.getKey(), entry.getValue());
mBleSourceInfoPreferenceCallback.onBroadcastSourceInfoRemoved(entry.getValue());
}
mPreferenceMap.clear();
}
@Override
public void onDeviceAttributesChanged() {
BroadcastScanAssistanceUtils.debug(TAG, "onDeviceAttributesChanged");
forceUpdate();
}
/**
* Set the context to generate the {@link Preference}, so it could get the correct theme.
*/
public void setPrefContext(Context context) {
mPrefContext = context;
}
/**
* Update whether to show {@link CachedBluetoothDevice} in the list.
*/
protected void update(Integer index, BleBroadcastSourceInfo sourceInfo) {
addPreference(index, sourceInfo);
}
/**
* Add the {@link Preference} that represents the {@code cachedDevice}
*/
protected void addPreference(Integer index, BleBroadcastSourceInfo sourceInfo) {
final BluetoothDevice device = sourceInfo.getSourceDevice();
final byte sourceId = sourceInfo.getSourceId();
if (mPreferenceMap.containsKey(index) == false) {
BroadcastScanAssistanceUtils.debug(TAG, "source info addition");
BleBroadcastSourceInfoPreference sourceInfoPreference =
new BleBroadcastSourceInfoPreference(mPrefContext,
mCachedDevice,
sourceInfo,
index,
BleBroadcastSourceInfoPreference.SortType.TYPE_DEFAULT);
sourceInfoPreference.setOnGearClickListener(mSourceInfoEntryListener);
if (this instanceof Preference.OnPreferenceClickListener) {
sourceInfoPreference.setOnPreferenceClickListener(
(Preference.OnPreferenceClickListener)this);
}
BroadcastScanAssistanceUtils.debug(TAG, "source info newly added: " + index);
mPreferenceMap.put(index, sourceInfoPreference);
mBleSourceInfoPreferenceCallback.onBroadcastSourceInfoAdded(sourceInfoPreference);
} else {
BleBroadcastSourceInfoPreference pref = (BleBroadcastSourceInfoPreference)mPreferenceMap.get(index);
BleBroadcastSourceInfo currentSi = pref.getBleBroadcastSourceInfo();
if (currentSi != null && currentSi.equals(sourceInfo)) {
BroadcastScanAssistanceUtils.debug(TAG, "No change in SI" + index);
} else {
BroadcastScanAssistanceUtils.debug(TAG, "source info Updated: " + index);
pref.setBleBroadcastSourceInfo (sourceInfo);
/*mBleSourceInfoPreferenceCallback.onBroadcastSourceInfoRemoved(mPreferenceMap.get(index));
mPreferenceMap.remove(index);
BleBroadcastSourceInfoPreference sourceInfoPreference =
new BleBroadcastSourceInfoPreference(mPrefContext,
mCachedDevice,
sourceInfo,
index,
BleBroadcastSourceInfoPreference.SortType.TYPE_DEFAULT);
sourceInfoPreference.setOnGearClickListener(mSourceInfoEntryListener);
if (this instanceof Preference.OnPreferenceClickListener) {
sourceInfoPreference.setOnPreferenceClickListener(
(Preference.OnPreferenceClickListener)this);
}
BroadcastScanAssistanceUtils.debug(TAG, "source info added again: " + index);
mPreferenceMap.put(index, sourceInfoPreference);
mBleSourceInfoPreferenceCallback.onBroadcastSourceInfoAdded(sourceInfoPreference);*/
}
}
}
/**
* Remove the {@link Preference} that represents the {@code cachedDevice}
*/
protected void removePreference(int index, Preference pref) {
if (mPreferenceMap.containsKey(index)) {
mBleSourceInfoPreferenceCallback.onBroadcastSourceInfoRemoved(mPreferenceMap.get(index));
mPreferenceMap.remove(index);
}
}
/**
* Get {@link CachedBluetoothDevice} from {@link Preference} and it is used to init
* {@link SubSettingLauncher} to launch {@link BluetoothDeviceDetailsFragment}
*/
protected void launchSourceInfoDetails(Preference preference) {
final BleBroadcastSourceInfo srcInfo =
((BleBroadcastSourceInfoPreference) preference).getBleBroadcastSourceInfo();
if (srcInfo == null) {
return;
}
final int index = ((BleBroadcastSourceInfoPreference) preference).getSourceInfoIndex();
final Bundle args = new Bundle();
args.putString(BleBroadcastSourceInfoDetailsFragment.KEY_DEVICE_ADDRESS,
mCachedDevice.getAddress());
args.putParcelable(BleBroadcastSourceInfoDetailsFragment.KEY_SOURCE_INFO,
srcInfo);
args.putInt(BleBroadcastSourceInfoDetailsFragment.KEY_SOURCE_INFO_INDEX,
index);
new SubSettingLauncher(mFragment.getContext())
.setDestination(BleBroadcastSourceInfoDetailsFragment.class.getName())
.setArguments(args)
.setTitleRes(R.string.source_info_details_title)
.setSourceMetricsCategory(mFragment.getMetricsCategory())
.launch();
}
}