Merge "[LE boradcast] save the data into ContentProvider" into tm-qpr-dev

This commit is contained in:
SongFerng Wang
2022-09-13 20:02:07 +00:00
committed by Android (Google) Code Review
4 changed files with 185 additions and 64 deletions

View File

@@ -6659,6 +6659,26 @@ public final class Settings {
@SuppressLint("NoSettingsProvider")
public static final String BLUETOOTH_ADDR_VALID = "bluetooth_addr_valid";
/**
* This is used by LocalBluetoothLeBroadcast to store the broadcast program info.
* @hide
*/
public static final String BLUETOOTH_LE_BROADCAST_PROGRAM_INFO =
"bluetooth_le_broadcast_program_info";
/**
* This is used by LocalBluetoothLeBroadcast to store the broadcast code.
* @hide
*/
public static final String BLUETOOTH_LE_BROADCAST_CODE = "bluetooth_le_broadcast_code";
/**
* This is used by LocalBluetoothLeBroadcast to store the app source name.
* @hide
*/
public static final String BLUETOOTH_LE_BROADCAST_APP_SOURCE_NAME =
"bluetooth_le_broadcast_app_source_name";
/**
* Setting to indicate that on device captions are enabled.
*

View File

@@ -26,11 +26,17 @@ import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothLeAudioContentMetadata;
import android.bluetooth.BluetoothLeBroadcast;
import android.bluetooth.BluetoothLeBroadcastMetadata;
import android.bluetooth.BluetoothLeBroadcastSubgroup;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.BluetoothProfile.ServiceListener;
import android.content.ContentResolver;
import android.content.Context;
import android.content.SharedPreferences;
import android.database.ContentObserver;
import android.net.Uri;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.Log;
@@ -40,6 +46,7 @@ import com.android.settingslib.R;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.UUID;
@@ -54,19 +61,20 @@ import java.util.concurrent.ThreadLocalRandom;
*/
public class LocalBluetoothLeBroadcast implements LocalBluetoothProfile {
private static final String TAG = "LocalBluetoothLeBroadcast";
private static final int UNKNOWN_VALUE_PLACEHOLDER = -1;
private static final boolean DEBUG = BluetoothUtils.D;
static final String NAME = "LE_AUDIO_BROADCAST";
private static final String UNDERLINE = "_";
private static final int DEFAULT_CODE_MAX = 9999;
private static final int DEFAULT_CODE_MIN = 1000;
// Order of this profile in device profiles list
private static final int ORDINAL = 1;
private static final String PREF_NAME = "LocalBluetoothLeBroadcast";
private static final String PREF_PROGRAM_INFO = "PrefProgramInfo";
private static final String PREF_BROADCAST_CODE = "PrefBroadcastCode";
private static final String PREF_APP_SOURCE_NAME = "PrefAppSourceName";
private static final String UNDERLINE = "_";
private static final int DEFAULT_CODE_MIN = 1000;
private static final int DEFAULT_CODE_MAX = 9999;
private static final int UNKNOWN_VALUE_PLACEHOLDER = -1;
private static final Uri[] SETTINGS_URIS = new Uri[]{
Settings.Secure.getUriFor(Settings.Secure.BLUETOOTH_LE_BROADCAST_PROGRAM_INFO),
Settings.Secure.getUriFor(Settings.Secure.BLUETOOTH_LE_BROADCAST_CODE),
Settings.Secure.getUriFor(Settings.Secure.BLUETOOTH_LE_BROADCAST_APP_SOURCE_NAME),
};
private BluetoothLeBroadcast mService;
private BluetoothLeAudioContentMetadata mBluetoothLeAudioContentMetadata;
@@ -78,8 +86,9 @@ public class LocalBluetoothLeBroadcast implements LocalBluetoothProfile {
private boolean mIsProfileReady;
private String mProgramInfo;
private byte[] mBroadcastCode;
private SharedPreferences mSharedPref;
private Executor mExecutor;
private ContentResolver mContentResolver;
private ContentObserver mSettingsObserver;
private final ServiceListener mServiceListener = new ServiceListener() {
@Override
@@ -91,6 +100,11 @@ public class LocalBluetoothLeBroadcast implements LocalBluetoothProfile {
mService = (BluetoothLeBroadcast) proxy;
mIsProfileReady = true;
registerServiceCallBack(mExecutor, mBroadcastCallback);
List<BluetoothLeBroadcastMetadata> metadata = getAllBroadcastMetadata();
if (!metadata.isEmpty()) {
updateBroadcastInfoFromBroadcastMetadata(metadata.get(0));
}
registerContentObserver();
}
}
@@ -102,6 +116,7 @@ public class LocalBluetoothLeBroadcast implements LocalBluetoothProfile {
if(mIsProfileReady) {
mIsProfileReady = false;
unregisterServiceCallBack(mBroadcastCallback);
unregisterContentObserver();
}
}
};
@@ -116,7 +131,7 @@ public class LocalBluetoothLeBroadcast implements LocalBluetoothProfile {
+ broadcastId);
}
setLatestBroadcastId(broadcastId);
setAppSourceName(mNewAppSourceName);
setAppSourceName(mNewAppSourceName, /*updateContentResolver=*/ true);
}
@Override
@@ -160,7 +175,7 @@ public class LocalBluetoothLeBroadcast implements LocalBluetoothProfile {
+ broadcastId);
}
setLatestBroadcastId(broadcastId);
setAppSourceName(mNewAppSourceName);
setAppSourceName(mNewAppSourceName, /*updateContentResolver=*/ true);
}
@Override
@@ -181,30 +196,27 @@ public class LocalBluetoothLeBroadcast implements LocalBluetoothProfile {
}
};
private class BroadcastSettingsObserver extends ContentObserver {
BroadcastSettingsObserver(Handler h) {
super(h);
}
@Override
public void onChange(boolean selfChange) {
Log.d(TAG, "BroadcastSettingsObserver: onChange");
updateBroadcastInfoFromContentProvider();
}
}
LocalBluetoothLeBroadcast(Context context) {
mExecutor = Executors.newSingleThreadExecutor();
BluetoothAdapter.getDefaultAdapter().
getProfileProxy(context, mServiceListener, BluetoothProfile.LE_AUDIO_BROADCAST);
mBuilder = new BluetoothLeAudioContentMetadata.Builder();
mSharedPref = context.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE);
if (mSharedPref != null) {
String programInfo = mSharedPref.getString(PREF_PROGRAM_INFO, "");
if (programInfo.isEmpty()) {
programInfo = getDefaultValueOfProgramInfo();
}
setProgramInfo(programInfo);
String prefBroadcastCode = mSharedPref.getString(PREF_BROADCAST_CODE, "");
byte[] broadcastCode;
if (prefBroadcastCode.isEmpty()) {
broadcastCode = getDefaultValueOfBroadcastCode();
} else {
broadcastCode = prefBroadcastCode.getBytes(StandardCharsets.UTF_8);
}
setBroadcastCode(broadcastCode);
mAppSourceName = mSharedPref.getString(PREF_APP_SOURCE_NAME, "");
}
mContentResolver = context.getContentResolver();
Handler handler = new Handler(Looper.getMainLooper());
mSettingsObserver = new BroadcastSettingsObserver(handler);
updateBroadcastInfoFromContentProvider();
}
/**
@@ -217,11 +229,12 @@ public class LocalBluetoothLeBroadcast implements LocalBluetoothProfile {
Log.d(TAG, "The BluetoothLeBroadcast is null when starting the broadcast.");
return;
}
String programInfo = getProgramInfo();
if (DEBUG) {
Log.d(TAG,
"startBroadcast: language = " + language + " ,programInfo = " + mProgramInfo);
"startBroadcast: language = " + language + " ,programInfo = " + programInfo);
}
buildContentMetadata(language, mProgramInfo);
buildContentMetadata(language, programInfo);
mService.startBroadcast(mBluetoothLeAudioContentMetadata, mBroadcastCode);
}
@@ -230,21 +243,28 @@ public class LocalBluetoothLeBroadcast implements LocalBluetoothProfile {
}
public void setProgramInfo(String programInfo) {
if (programInfo == null || programInfo.isEmpty()) {
setProgramInfo(programInfo, /*updateContentResolver=*/ true);
}
private void setProgramInfo(String programInfo, boolean updateContentResolver) {
if (TextUtils.isEmpty(programInfo)) {
Log.d(TAG, "setProgramInfo: programInfo is null or empty");
return;
}
if (mProgramInfo != null && TextUtils.equals(mProgramInfo, programInfo)) {
Log.d(TAG, "setProgramInfo: programInfo is not changed");
return;
}
Log.d(TAG, "setProgramInfo: " + programInfo);
mProgramInfo = programInfo;
if (mSharedPref == null) {
Log.d(TAG, "setProgramInfo: sharedPref is null");
return;
if (updateContentResolver) {
if (mContentResolver == null) {
Log.d(TAG, "mContentResolver is null");
return;
}
Settings.Secure.putString(mContentResolver,
Settings.Secure.BLUETOOTH_LE_BROADCAST_PROGRAM_INFO, programInfo);
}
SharedPreferences.Editor editor = mSharedPref.edit();
editor.putString(PREF_PROGRAM_INFO, mProgramInfo);
editor.apply();
}
public byte[] getBroadcastCode() {
@@ -252,22 +272,31 @@ public class LocalBluetoothLeBroadcast implements LocalBluetoothProfile {
}
public void setBroadcastCode(byte[] broadcastCode) {
if (broadcastCode == null || broadcastCode.length == 0) {
Log.d(TAG, "setBroadcastCode: broadcastCode is null or empty");
setBroadcastCode(broadcastCode, /*updateContentResolver=*/ true);
}
private void setBroadcastCode(byte[] broadcastCode, boolean updateContentResolver) {
if (broadcastCode == null) {
Log.d(TAG, "setBroadcastCode: broadcastCode is null");
return;
}
if (mBroadcastCode != null && Arrays.equals(broadcastCode, mBroadcastCode)) {
Log.d(TAG, "setBroadcastCode: broadcastCode is not changed");
return;
}
mBroadcastCode = broadcastCode;
if (mSharedPref == null) {
Log.d(TAG, "setBroadcastCode: sharedPref is null");
return;
if (updateContentResolver) {
if (mContentResolver == null) {
Log.d(TAG, "mContentResolver is null");
return;
}
Settings.Secure.putString(mContentResolver, Settings.Secure.BLUETOOTH_LE_BROADCAST_CODE,
new String(broadcastCode, StandardCharsets.UTF_8));
}
SharedPreferences.Editor editor = mSharedPref.edit();
editor.putString(PREF_BROADCAST_CODE, new String(broadcastCode, StandardCharsets.UTF_8));
editor.apply();
}
private void setLatestBroadcastId(int broadcastId) {
Log.d(TAG, "setLatestBroadcastId: mBroadcastId is " + broadcastId);
mBroadcastId = broadcastId;
}
@@ -275,19 +304,24 @@ public class LocalBluetoothLeBroadcast implements LocalBluetoothProfile {
return mBroadcastId;
}
private void setAppSourceName(String appSourceName) {
private void setAppSourceName(String appSourceName, boolean updateContentResolver) {
if (TextUtils.isEmpty(appSourceName)) {
appSourceName = "";
}
mAppSourceName = appSourceName;
mNewAppSourceName = "";
if (mSharedPref == null) {
Log.d(TAG, "setBroadcastCode: sharedPref is null");
if (mAppSourceName != null && TextUtils.equals(mAppSourceName, appSourceName)) {
Log.d(TAG, "setAppSourceName: appSourceName is not changed");
return;
}
SharedPreferences.Editor editor = mSharedPref.edit();
editor.putString(PREF_APP_SOURCE_NAME, appSourceName);
editor.apply();
mAppSourceName = appSourceName;
mNewAppSourceName = "";
if (updateContentResolver) {
if (mContentResolver == null) {
Log.d(TAG, "mContentResolver is null");
return;
}
Settings.Secure.putString(mContentResolver,
Settings.Secure.BLUETOOTH_LE_BROADCAST_APP_SOURCE_NAME, mAppSourceName);
}
}
public String getAppSourceName() {
@@ -299,6 +333,7 @@ public class LocalBluetoothLeBroadcast implements LocalBluetoothProfile {
if (bluetoothLeBroadcastMetadata != null
&& bluetoothLeBroadcastMetadata.getBroadcastId() == mBroadcastId) {
mBluetoothLeBroadcastMetadata = bluetoothLeBroadcastMetadata;
updateBroadcastInfoFromBroadcastMetadata(bluetoothLeBroadcastMetadata);
}
}
@@ -318,6 +353,48 @@ public class LocalBluetoothLeBroadcast implements LocalBluetoothProfile {
return mBluetoothLeBroadcastMetadata;
}
private void updateBroadcastInfoFromContentProvider() {
if (mContentResolver == null) {
Log.d(TAG, "updateBroadcastInfoFromContentProvider: mContentResolver is null");
return;
}
String programInfo = Settings.Secure.getString(mContentResolver,
Settings.Secure.BLUETOOTH_LE_BROADCAST_PROGRAM_INFO);
if (programInfo == null) {
programInfo = getDefaultValueOfProgramInfo();
}
setProgramInfo(programInfo, /*updateContentResolver=*/ false);
String prefBroadcastCode = Settings.Secure.getString(mContentResolver,
Settings.Secure.BLUETOOTH_LE_BROADCAST_CODE);
byte[] broadcastCode = (prefBroadcastCode == null) ? getDefaultValueOfBroadcastCode()
: prefBroadcastCode.getBytes(StandardCharsets.UTF_8);
setBroadcastCode(broadcastCode, /*updateContentResolver=*/ false);
String appSourceName = Settings.Secure.getString(mContentResolver,
Settings.Secure.BLUETOOTH_LE_BROADCAST_APP_SOURCE_NAME);
setAppSourceName(appSourceName, /*updateContentResolver=*/ false);
}
private void updateBroadcastInfoFromBroadcastMetadata(
BluetoothLeBroadcastMetadata bluetoothLeBroadcastMetadata) {
if (bluetoothLeBroadcastMetadata == null) {
Log.d(TAG, "The bluetoothLeBroadcastMetadata is null");
return;
}
setBroadcastCode(bluetoothLeBroadcastMetadata.getBroadcastCode());
setLatestBroadcastId(bluetoothLeBroadcastMetadata.getBroadcastId());
List<BluetoothLeBroadcastSubgroup> subgroup = bluetoothLeBroadcastMetadata.getSubgroups();
if (subgroup == null || subgroup.size() < 1) {
Log.d(TAG, "The subgroup is not valid value");
return;
}
BluetoothLeAudioContentMetadata contentMetadata = subgroup.get(0).getContentMetadata();
setProgramInfo(contentMetadata.getProgramInfo());
setAppSourceName(getAppSourceName(), /*updateContentResolver=*/ true);
}
/**
* Stop the latest LE Broadcast. If the system stopped the LE Broadcast, then the system
* calls the corresponding callback {@link BluetoothLeBroadcast.Callback}.
@@ -350,12 +427,13 @@ public class LocalBluetoothLeBroadcast implements LocalBluetoothProfile {
Log.d(TAG, "The BluetoothLeBroadcast is null when updating the broadcast.");
return;
}
String programInfo = getProgramInfo();
if (DEBUG) {
Log.d(TAG,
"updateBroadcast: language = " + language + " ,programInfo = " + mProgramInfo);
"updateBroadcast: language = " + language + " ,programInfo = " + programInfo);
}
mNewAppSourceName = appSourceName;
mBluetoothLeAudioContentMetadata = mBuilder.setProgramInfo(mProgramInfo).build();
mBluetoothLeAudioContentMetadata = mBuilder.setProgramInfo(programInfo).build();
mService.updateBroadcast(mBroadcastId, mBluetoothLeAudioContentMetadata);
}
@@ -517,8 +595,7 @@ public class LocalBluetoothLeBroadcast implements LocalBluetoothProfile {
if (DEBUG) {
Log.d(TAG, "resetCacheInfo:");
}
mNewAppSourceName = "";
mAppSourceName = "";
setAppSourceName("", /*updateContentResolver=*/ true);
mBluetoothLeBroadcastMetadata = null;
mBroadcastId = UNKNOWN_VALUE_PLACEHOLDER;
}
@@ -528,4 +605,22 @@ public class LocalBluetoothLeBroadcast implements LocalBluetoothProfile {
//first 12 chars from xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx
return randomUUID.substring(0, 8) + randomUUID.substring(9, 13);
}
private void registerContentObserver() {
if (mContentResolver == null) {
Log.d(TAG, "mContentResolver is null");
return;
}
for (Uri uri : SETTINGS_URIS) {
mContentResolver.registerContentObserver(uri, false, mSettingsObserver);
}
}
private void unregisterContentObserver() {
if (mContentResolver == null) {
Log.d(TAG, "mContentResolver is null");
return;
}
mContentResolver.unregisterContentObserver(mSettingsObserver);
}
}

View File

@@ -212,6 +212,9 @@ public class SecureSettings {
Settings.Secure.LOCKSCREEN_USE_DOUBLE_LINE_CLOCK,
Settings.Secure.STATUS_BAR_SHOW_VIBRATE_ICON,
Settings.Secure.ASSIST_TOUCH_GESTURE_ENABLED,
Settings.Secure.ASSIST_LONG_PRESS_HOME_ENABLED
Settings.Secure.ASSIST_LONG_PRESS_HOME_ENABLED,
Settings.Secure.BLUETOOTH_LE_BROADCAST_PROGRAM_INFO,
Settings.Secure.BLUETOOTH_LE_BROADCAST_CODE,
Settings.Secure.BLUETOOTH_LE_BROADCAST_APP_SOURCE_NAME
};
}

View File

@@ -344,5 +344,8 @@ public class SecureSettingsValidators {
return true;
});
VALIDATORS.put(Secure.ODI_CAPTIONS_VOLUME_UI_ENABLED, BOOLEAN_VALIDATOR);
VALIDATORS.put(Secure.BLUETOOTH_LE_BROADCAST_PROGRAM_INFO, ANY_STRING_VALIDATOR);
VALIDATORS.put(Secure.BLUETOOTH_LE_BROADCAST_CODE, ANY_STRING_VALIDATOR);
VALIDATORS.put(Secure.BLUETOOTH_LE_BROADCAST_APP_SOURCE_NAME, ANY_STRING_VALIDATOR);
}
}