Merge "[LE boradcast] save the data into ContentProvider" into tm-qpr-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
86125487ca
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user