1. Overview
- System_server 绑定蓝牙服务时,启动 com.android.bluetooth 进程。
- 首先执行 Application 的子类,即 AdapterApp.java,加载 libbluetooth_jni.so,加载可开启的 Profiles 配置信息;
- 随后执行被绑定服务类,即 AdapterService.java,初始化 JNI,启动蓝牙适配器服务。
2. Application initialization
packages/apps/Bluetooth/src/com/android/bluetooth/btservice/AdapterApp.java
public class AdapterApp extends Application {
static {
System.loadLibrary("bluetooth_jni"); // 1
}
public AdapterApp() {
super();
}
@Override
public void onCreate() {
super.onCreate();
Config.init(this); // 2
}
}
2.1 System.loadLibrary("bluetooth_jni")
加载 libbluetooth_jni.so ,具体如何加载,参考 System.loadLibrary(libname)
2.2 Load Supported Profiles Config
读取配置信息,确定需要开启的 Profile 列表并存储。
packages/apps/Bluetooth/src/com/android/bluetooth/btservice/Config.java
public class Config {
static void init(Context ctx) {
......
Resources resources = ctx.getResources();
// 下面的循环遍历中第3个条件
List<String> enabledProfiles = getSystemConfigEnabledProfilesForPackage(ctx);
ArrayList<Class> profiles = new ArrayList<>(PROFILE_SERVICES_AND_FLAGS.length);
for (ProfileConfig config : PROFILE_SERVICES_AND_FLAGS) {
// 1 读取默认配置的开启状态
boolean supported = resources.getBoolean(config.mSupported);
// 2 HearingAid 若不支持,则继续查询特定的配置(两者有一个开启,则开启)
if (!supported && (config.mClass == HearingAidService.class) && isHearingAidSettingsEnabled(ctx)) {
supported = true;
}
// 3 查询优先级更高的配置,二者有一个开启,则开启该 profile
if (enabledProfiles != null && enabledProfiles.contains(config.mClass.getName())) {
supported = true;
}
// 4 查询更高优先级的配置,若指定关闭,则应该关闭,否则添加到开启的列表
if (supported && !isProfileDisabled(ctx, config.mMask)) {
profiles.add(config.mClass);
}
}
// 根据配置信息和既定规则,确定支持的 profile list
sSupportedProfiles = profiles.toArray(new Class[profiles.size()]);
// Gabledorsche 协议栈有关配置,由下面的配置文件可知,此处是开启的
sIsGdEnabledUptoScanningLayer = resources.getBoolean(R.bool.enable_gd_up_to_scanning_layer);
}
}
2.2.1 Default Config
public class Config {
private static class ProfileConfig {
Class mClass;
int mSupported;
long mMask;
ProfileConfig(Class theClass, int supportedFlag, long mask) {
mClass = theClass;
mSupported = supportedFlag;
mMask = mask;
}
}
private static final ProfileConfig[] PROFILE_SERVICES_AND_FLAGS = {
new ProfileConfig(HeadsetService.class, R.bool.profile_supported_hs_hfp,
(1 << BluetoothProfile.HEADSET)),
new ProfileConfig(A2dpService.class, R.bool.profile_supported_a2dp,
(1 << BluetoothProfile.A2DP)),
new ProfileConfig(A2dpSinkService.class, R.bool.profile_supported_a2dp_sink,
(1 << BluetoothProfile.A2DP_SINK)),
new ProfileConfig(HidHostService.class, R.bool.profile_supported_hid_host,
(1 << BluetoothProfile.HID_HOST)),
new ProfileConfig(PanService.class, R.bool.profile_supported_pan,
(1 << BluetoothProfile.PAN)),
new ProfileConfig(GattService.class, R.bool.profile_supported_gatt,
(1 << BluetoothProfile.GATT)),
new ProfileConfig(BluetoothMapService.class, R.bool.profile_supported_map,
(1 << BluetoothProfile.MAP)),
new ProfileConfig(HeadsetClientService.class, R.bool.profile_supported_hfpclient,
(1 << BluetoothProfile.HEADSET_CLIENT)),
new ProfileConfig(AvrcpTargetService.class, R.bool.profile_supported_avrcp_target,
(1 << BluetoothProfile.AVRCP)),
new ProfileConfig(AvrcpControllerService.class,
R.bool.profile_supported_avrcp_controller,
(1 << BluetoothProfile.AVRCP_CONTROLLER)),
new ProfileConfig(SapService.class, R.bool.profile_supported_sap,
(1 << BluetoothProfile.SAP)),
new ProfileConfig(PbapClientService.class, R.bool.profile_supported_pbapclient,
(1 << BluetoothProfile.PBAP_CLIENT)),
new ProfileConfig(MapClientService.class, R.bool.profile_supported_mapmce,
(1 << BluetoothProfile.MAP_CLIENT)),
new ProfileConfig(HidDeviceService.class, R.bool.profile_supported_hid_device,
(1 << BluetoothProfile.HID_DEVICE)),
new ProfileConfig(BluetoothOppService.class, R.bool.profile_supported_opp,
(1 << BluetoothProfile.OPP)),
new ProfileConfig(BluetoothPbapService.class, R.bool.profile_supported_pbap,
(1 << BluetoothProfile.PBAP)),
new ProfileConfig(LeAudioService.class, R.bool.profile_supported_le_audio,
(1 << BluetoothProfile.LE_AUDIO)),
new ProfileConfig(VolumeControlService.class, R.bool.profile_supported_vc,
(1 << BluetoothProfile.VOLUME_CONTROL)),
new ProfileConfig(McpService.class, R.bool.profile_supported_mcp_server,
(1 << BluetoothProfile.MCP_SERVER)),
new ProfileConfig(HearingAidService.class,
com.android.internal.R.bool.config_hearing_aid_profile_supported,
(1 << BluetoothProfile.HEARING_AID)),
new ProfileConfig(CsipSetCoordinatorService.class,
R.bool.profile_supported_csip_set_coordinator,
(1 << BluetoothProfile.CSIP_SET_COORDINATOR)),
};
}
以上 Profile 的开关配置如下:
packages/apps/Bluetooth/res/values/config.xml
<bool name="profile_supported_a2dp">true</bool>
<bool name="profile_supported_a2dp_sink">false</bool> // false
<bool name="profile_supported_hs_hfp">true</bool>
<bool name="profile_supported_hfpclient">false</bool> // false
<bool name="profile_supported_hfp_incallservice">true</bool>
<bool name="profile_supported_hid_host">true</bool>
<bool name="profile_supported_opp">true</bool>
<bool name="profile_supported_pan">true</bool>
<bool name="profile_supported_pbap">true</bool>
<bool name="profile_supported_gatt">true</bool>
<bool name="pbap_include_photos_in_vcard">true</bool>
<bool name="pbap_use_profile_for_owner_vcard">true</bool>
<bool name="profile_supported_map">true</bool>
<bool name="profile_supported_avrcp_target">true</bool>
<bool name="profile_supported_avrcp_controller">false</bool> // false
<bool name="profile_supported_sap">false</bool> // false
<bool name="profile_supported_pbapclient">false</bool> // false
<bool name="profile_supported_mapmce">false</bool> // false
<bool name="profile_supported_hid_device">true</bool>
<bool name="profile_supported_le_audio">true</bool>
<bool name="profile_supported_vc">true</bool>
<bool name="profile_supported_mcp_server">true</bool>
<bool name="profile_supported_csip_set_coordinator">true</bool>
<bool name="enable_gd_up_to_scanning_layer">true</bool>
2.2.2 HearingAid
private static boolean isHearingAidSettingsEnabled(Context context) {
final String flagOverridePrefix = "sys.fflag.override.";
final String hearingAidSettings = "settings_bluetooth_hearing_aid";
// Override precedence:
// Settings.Global -> sys.fflag.override.* -> static list
// Step 1: check if hearing aid flag is set in Settings.Global.
String value;
if (context != null) {
value = Settings.Global.getString(context.getContentResolver(), hearingAidSettings);
if (!TextUtils.isEmpty(value)) {
return Boolean.parseBoolean(value);
}
}
// Step 2: check if hearing aid flag has any override.
value = SystemProperties.get(flagOverridePrefix + hearingAidSettings);
if (!TextUtils.isEmpty(value)) {
return Boolean.parseBoolean(value);
}
// Step 3: return default value.
return false;
}
- 通过 Settings 数据库查询配置
- 通过 SystemProperties 查询配置
2.2.3 System Config
从上文源代码分析可知,这里只是获取 System Config 对 profile 的配置。
挖坑待填 // todo
private static List<String> getSystemConfigEnabledProfilesForPackage(Context ctx) {
SystemConfigManager systemConfigManager = ctx.getSystemService(SystemConfigManager.class);
if (systemConfigManager == null) {
return null;
}
return systemConfigManager.getEnabledComponentOverrides(ctx.getPackageName());
}
frameworks/base/core/java/android/os/SystemConfigManager.java
@SystemApi
@NonNull
public List<String> getEnabledComponentOverrides(@NonNull String packageName) {
try {
return mInterface.getEnabledComponentOverrides(packageName);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
2.2.4 Profile Disabled
private static boolean isProfileDisabled(Context context, long profileMask) {
final ContentResolver resolver = context.getContentResolver();
final long disabledProfilesBitMask =
Settings.Global.getLong(resolver, Settings.Global.BLUETOOTH_DISABLED_PROFILES, 0);
return (disabledProfilesBitMask & profileMask) != 0;
}
通过 Settings 数据库查询特定字段配置
3. AdapterService 初始化
packages/apps/Bluetooth/src/com/android/bluetooth/btservice/AdapterService.java
- 首先,执行静态代码块,初始化 JNI;
- 其次,执行 AdapterService 的 onCreate() 方法;
- 最后,执行 onBind() 方法,返回 IBinder 子类对象。
3.1 初始化 JNI
前文已经加载了 libbluetooth_jni.so,这里开始初始化 JNI。
public class AdapterService extends Service {
static {
classInitNative();
}
static native void classInitNative();
}
packages/apps/Bluetooth/jni/com_android_bluetooth_btservice_AdapterService.cpp
static void classInitNative(JNIEnv* env, jclass clazz) {
jclass jniUidTrafficClass = env->FindClass("android/bluetooth/UidTraffic");
android_bluetooth_UidTraffic.constructor =
env->GetMethodID(jniUidTrafficClass, "<init>", "(IJJ)V");
jclass jniCallbackClass =
env->FindClass("com/android/bluetooth/btservice/JniCallbacks");
sJniCallbacksField = env->GetFieldID(
clazz, "mJniCallbacks", "Lcom/android/bluetooth/btservice/JniCallbacks;");
method_oobDataReceivedCallback =
env->GetMethodID(jniCallbackClass, "oobDataReceivedCallback",
"(ILandroid/bluetooth/OobData;)V");
method_stateChangeCallback =
env->GetMethodID(jniCallbackClass, "stateChangeCallback", "(I)V");
method_adapterPropertyChangedCallback = env->GetMethodID(
jniCallbackClass, "adapterPropertyChangedCallback", "([I[[B)V");
method_discoveryStateChangeCallback = env->GetMethodID(
jniCallbackClass, "discoveryStateChangeCallback", "(I)V");
method_devicePropertyChangedCallback = env->GetMethodID(
jniCallbackClass, "devicePropertyChangedCallback", "([B[I[[B)V");
method_deviceFoundCallback =
env->GetMethodID(jniCallbackClass, "deviceFoundCallback", "([B)V");
method_pinRequestCallback =
env->GetMethodID(jniCallbackClass, "pinRequestCallback", "([B[BIZ)V");
method_sspRequestCallback =
env->GetMethodID(jniCallbackClass, "sspRequestCallback", "([B[BIII)V");
method_bondStateChangeCallback =
env->GetMethodID(jniCallbackClass, "bondStateChangeCallback", "(I[BII)V");
method_aclStateChangeCallback =
env->GetMethodID(jniCallbackClass, "aclStateChangeCallback", "(I[BIII)V");
method_linkQualityReportCallback = env->GetMethodID(
jniCallbackClass, "linkQualityReportCallback", "(JIIIIII)V");
method_setWakeAlarm = env->GetMethodID(clazz, "setWakeAlarm", "(JZ)Z");
method_acquireWakeLock =
env->GetMethodID(clazz, "acquireWakeLock", "(Ljava/lang/String;)Z");
method_releaseWakeLock =
env->GetMethodID(clazz, "releaseWakeLock", "(Ljava/lang/String;)Z");
method_energyInfo = env->GetMethodID(
clazz, "energyInfoCallback", "(IIJJJJ[Landroid/bluetooth/UidTraffic;)V");
if (env->GetJavaVM(&vm) != JNI_OK) {
ALOGE("Could not get JavaVM");
}
if (hal_util_load_bt_library((bt_interface_t const**)&sBluetoothInterface)) {
ALOGE("No Bluetooth Library found");
}
}
int hal_util_load_bt_library(const bt_interface_t** interface) {
const char* sym = BLUETOOTH_INTERFACE_STRING;
bt_interface_t* itf = nullptr;
// The library name is not set by default, so the preset library name is used.
void* handle = dlopen("libbluetooth.so", RTLD_NOW);
......
// Get the address of the bt_interface_t.
itf = (bt_interface_t*)dlsym(handle, sym);
......
// Success.
*interface = itf;
return 0;
......
}
system/bt/include/hardware/bluetooth.h
#define BLUETOOTH_INTERFACE_STRING "bluetoothInterface"
注意: 该函数加载并打开了 libbluetooth.so 库文件,sBluetoothInterface 变量是 JNI 调用 libbluetooth.so 内容的入口。
根据 sym 可知,入口内容如下:
system/bt/btif/src/bluetooth.cc
EXPORT_SYMBOL bt_interface_t bluetoothInterface = {
sizeof(bluetoothInterface),
init,
enable,
disable,
cleanup,
get_adapter_properties,
get_adapter_property,
set_adapter_property,
get_remote_device_properties,
get_remote_device_property,
set_remote_device_property,
nullptr,
get_remote_services,
start_discovery,
cancel_discovery,
create_bond,
create_bond_out_of_band,
remove_bond,
cancel_bond,
get_connection_state,
pin_reply,
ssp_reply,
get_profile_interface, // 通过它可以获取其他profile的入口
dut_mode_configure,
dut_mode_send,
le_test_mode,
set_os_callouts,
read_energy_info,
dump,
dumpMetrics,
config_clear,
interop_database_clear,
interop_database_add,
get_avrcp_service,
obfuscate_address,
get_metric_id,
set_dynamic_audio_buffer_size,
generate_local_oob_data
};
各种 profile 可以通过 get_profile_interface() 函数,获取到 profile 的入口。
该函数可以使用的有效ID如下:
system/bt/include/hardware/bluetooth.h
/** Bluetooth profile interface IDs */
#define BT_PROFILE_HANDSFREE_ID "handsfree"
#define BT_PROFILE_HANDSFREE_CLIENT_ID "handsfree_client"
#define BT_PROFILE_ADVANCED_AUDIO_ID "a2dp"
#define BT_PROFILE_ADVANCED_AUDIO_SINK_ID "a2dp_sink"
#define BT_PROFILE_SOCKETS_ID "socket"
#define BT_PROFILE_HIDHOST_ID "hidhost"
#define BT_PROFILE_HIDDEV_ID "hiddev"
#define BT_PROFILE_PAN_ID "pan"
#define BT_PROFILE_MAP_CLIENT_ID "map_client"
#define BT_PROFILE_SDP_CLIENT_ID "sdp"
#define BT_PROFILE_GATT_ID "gatt"
#define BT_PROFILE_AV_RC_ID "avrcp"
#define BT_PROFILE_AV_RC_CTRL_ID "avrcp_ctrl"
#define BT_PROFILE_HEARING_AID_ID "hearing_aid"
#define BT_KEYSTORE_ID "bluetooth_keystore"
3.2 AdapterService 初始化
packages/apps/Bluetooth/src/com/android/bluetooth/btservice/AdapterService.java
public class AdapterService extends Service {
@Override
public void onCreate() {
super.onCreate();
// 1 负责解析蓝牙设备的扫描结果
mRemoteDevices = new RemoteDevices(this, Looper.getMainLooper());
mRemoteDevices.init();
// 清理调用 discovery() 的方法的包名的集合
clearDiscoveringPackages();
mBinder = new AdapterServiceBinder(this);
mAdapterProperties = new AdapterProperties(this);
mAdapterStateMachine = AdapterState.make(this);
mJniCallbacks = new JniCallbacks(this, mAdapterProperties);
// 2
mBluetoothKeystoreService = new BluetoothKeystoreService(isCommonCriteriaMode());
mBluetoothKeystoreService.start();
int configCompareResult = mBluetoothKeystoreService.getCompareResult();
// Android TV doesn't show consent dialogs for just works and encryption only le pairing
boolean isAtvDevice = getApplicationContext().getPackageManager().hasSystemFeature(
PackageManager.FEATURE_LEANBACK_ONLY);
// 3
initNative(isGuest(), isNiapMode(), configCompareResult, isAtvDevice);
mNativeAvailable = true;
mCallbacks = new RemoteCallbackList<IBluetoothCallback>();
// 4
getAdapterPropertyNative(AbstractionLayer.BT_PROPERTY_BDADDR);
getAdapterPropertyNative(AbstractionLayer.BT_PROPERTY_BDNAME);
getAdapterPropertyNative(AbstractionLayer.BT_PROPERTY_CLASS_OF_DEVICE);
mAlarmManager = getSystemService(AlarmManager.class);
mPowerManager = getSystemService(PowerManager.class);
mBatteryStatsManager = getSystemService(BatteryStatsManager.class);
// 2.1 为何不跟前面放在一起执行
mBluetoothKeystoreService.initJni();
// 5
mSdpManager = SdpManager.init(this);
registerReceiver(mAlarmBroadcastReceiver, new IntentFilter(ACTION_ALARM_WAKEUP));
// 6
mDatabaseManager = new DatabaseManager(this);
mDatabaseManager.start(MetadataDatabase.createDatabase(this));
// Phone policy is specific to phone implementations and hence if a device wants to exclude
// it out then it can be disabled by using the flag below.
if (getResources().getBoolean(com.android.bluetooth.R.bool.enable_phone_policy)) {
Log.i(TAG, "Phone policy enabled");
mPhonePolicy = new PhonePolicy(this, new ServiceFactory());
mPhonePolicy.start();
} else {
Log.i(TAG, "Phone policy disabled");
}
// 7
mActiveDeviceManager = new ActiveDeviceManager(this, new ServiceFactory());
mActiveDeviceManager.start();
// 8
mSilenceDeviceManager = new SilenceDeviceManager(this, new ServiceFactory(),
Looper.getMainLooper());
mSilenceDeviceManager.start();
// 9
mBluetoothSocketManagerBinder = new BluetoothSocketManagerBinder(this);
setAdapterService(this);
// 10
invalidateBluetoothCaches();
// First call to getSharedPreferences will result in a file read into
// memory cache. Call it here asynchronously to avoid potential ANR
// in the future
new AsyncTask<Void, Void, Void>() {
// 11
@Override
protected Void doInBackground(Void... params) {
getSharedPreferences(PHONEBOOK_ACCESS_PERMISSION_PREFERENCE_FILE,
Context.MODE_PRIVATE);
getSharedPreferences(MESSAGE_ACCESS_PERMISSION_PREFERENCE_FILE,
Context.MODE_PRIVATE);
getSharedPreferences(SIM_ACCESS_PERMISSION_PREFERENCE_FILE, Context.MODE_PRIVATE);
return null;
}
}.execute();
// 12
try {
int systemUiUid = getApplicationContext()
.createContextAsUser(UserHandle.SYSTEM, /* flags= */ 0)
.getPackageManager()
.getPackageUid("com.android.systemui", PackageManager.MATCH_SYSTEM_ONLY);
Utils.setSystemUiUid(systemUiUid);
} catch (PackageManager.NameNotFoundException e) {
// Some platforms, such as wearables do not have a system ui.
Log.w(TAG, "Unable to resolve SystemUI's UID.", e);
}
// 13
IntentFilter filter = new IntentFilter(Intent.ACTION_USER_SWITCHED);
getApplicationContext().registerReceiverForAllUsers(sUserSwitchedReceiver, filter, null, null);
int fuid = ActivityManager.getCurrentUser();
Utils.setForegroundUserId(fuid);
}
}
3.2.1 Remote Device 初始化
packages/apps/Bluetooth/src/com/android/bluetooth/btservice/RemoteDevices.java
final class RemoteDevices {
RemoteDevices(AdapterService service, Looper looper) {
sAdapter = BluetoothAdapter.getDefaultAdapter();
sAdapterService = service;
sSdpTracker = new ArrayList<BluetoothDevice>();
mDevices = new HashMap<String, DeviceProperties>();
mDeviceQueue = new LinkedList<String>();
mHandler = new RemoteDevicesHandler(looper);
}
void init() {
IntentFilter filter = new IntentFilter();
filter.addAction(BluetoothHeadset.ACTION_HF_INDICATORS_VALUE_CHANGED);
filter.addAction(BluetoothHeadset.ACTION_VENDOR_SPECIFIC_HEADSET_EVENT);
filter.addCategory(BluetoothHeadset.VENDOR_SPECIFIC_HEADSET_EVENT_COMPANY_ID_CATEGORY + "."
+ BluetoothAssignedNumbers.PLANTRONICS);
filter.addCategory(BluetoothHeadset.VENDOR_SPECIFIC_HEADSET_EVENT_COMPANY_ID_CATEGORY + "."
+ BluetoothAssignedNumbers.APPLE);
filter.addAction(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED);
sAdapterService.registerReceiver(mReceiver, filter);
}
class DeviceProperties {
private String mName;
private byte[] mAddress;
private int mBluetoothClass = BluetoothClass.Device.Major.UNCATEGORIZED;
private short mRssi;
private String mAlias;
private BluetoothDevice mDevice;
private boolean mIsBondingInitiatedLocally;
private int mBatteryLevel = BluetoothDevice.BATTERY_LEVEL_UNKNOWN;
@VisibleForTesting int mBondState;
@VisibleForTesting int mDeviceType;
@VisibleForTesting ParcelUuid[] mUuids;
......
}
}
RemoteDevices 用于解析和存储扫描发现的远程设备(对端设备)的信息
3.2.2 BluetoothKeystoreService 初始化
public class BluetoothKeystoreService {
public BluetoothKeystoreService(boolean isNiapMode) {
mIsNiapMode = isNiapMode;
mCompareResult = CONFIG_COMPARE_INIT;
startThread();
}
public void start() {
KeyStore keyStore = getKeyStore();
mBluetoothKeystoreNativeInterface = Objects.requireNonNull(
BluetoothKeystoreNativeInterface.getInstance(),
"BluetoothKeystoreNativeInterface cannot be null when BluetoothKeystore starts");
// Mark service as started
setBluetoothKeystoreService(this);
try {
if (!keyStore.containsAlias(KEYALIAS) && mIsNiapMode) {
mCompareResult = 0b11;
return;
}
} catch (KeyStoreException e) {
reportKeystoreException(e, "cannot find the keystore");
return;
}
// Load decryption data from file.
loadConfigData();
}
BluetoothKeystoreService 用于存储设备的密钥信息(LinkKey、LTK)
3.2.3 初始化 Native ( Bluetooth Stack )
Bluetooth Initialization - Native Initialization
3.2.4 getAdapterPropertyNative
从 Stack 获取蓝牙适配器的属性信息
3.2.5 SdpManager
packages/apps/Bluetooth/src/com/android/bluetooth/sdp/SdpManager.java
public class SdpManager {
public static SdpManager init(AdapterService adapterService) {
sSdpManager = new SdpManager(adapterService);
return sSdpManager;
}
private SdpManager(AdapterService adapterService) {
sSdpSearchTracker = new SdpSearchTracker();
sAdapterService = adapterService;
initializeNative();
sNativeAvailable = true;
}
private native void initializeNative();
}
packages/apps/Bluetooth/jni/com_android_bluetooth_sdp.cpp
static void initializeNative(JNIEnv* env, jobject object) {
const bt_interface_t* btInf = getBluetoothInterface();
sBluetoothSdpInterface = (btsdp_interface_t*)btInf->get_profile_interface(
BT_PROFILE_SDP_CLIENT_ID);
sBluetoothSdpInterface->init(&sBluetoothSdpCallbacks);
sCallbacksObj = env->NewGlobalRef(object);
}
初始化 SDP JNI,获取 SDP 客户端对象,用于 与 SDP 服务端相互操作。
3.2.6 DatabaseManager
packages/apps/Bluetooth/src/com/android/bluetooth/btservice/storage/DatabaseManager.java
public class DatabaseManager {
public DatabaseManager(AdapterService service) {
mAdapterService = service;
mMetadataChangedLog = EvictingQueue.create(METADATA_CHANGED_LOG_MAX_SIZE);
}
public void start(MetadataDatabase database) {
mDatabase = database;
mHandlerThread = new HandlerThread("BluetoothDatabaseManager");
mHandlerThread.start();
mHandler = new DatabaseHandler(mHandlerThread.getLooper());
IntentFilter filter = new IntentFilter();
filter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
mAdapterService.registerReceiver(mReceiver, filter);
loadDatabase();
}
private void loadDatabase() {
Message message = mHandler.obtainMessage(MSG_LOAD_DATABASE);
mHandler.sendMessage(message);
......
}
class DatabaseHandler extends Handler {
DatabaseHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_LOAD_DATABASE: {
synchronized (mDatabase) {
List<Metadata> list;
try {
list = mDatabase.load();
} catch (IllegalStateException e) {
mDatabase = MetadataDatabase
.createDatabaseWithoutMigration(mAdapterService);
list = mDatabase.load();
}
compactLastConnectionTime(list);
cacheMetadata(list);
}
break;
}
......
}
}
}
}
初始化数据库,随后读取数据库的内容,并转成合适的格式缓存在内存中。
3.2.7 ActiveDeviceManager
packages/apps/Bluetooth/src/com/android/bluetooth/btservice/ActiveDeviceManager.java
class ActiveDeviceManager {
ActiveDeviceManager(AdapterService service, ServiceFactory factory) {
mAdapterService = service;
mFactory = factory;
mAudioManager = (AudioManager) service.getSystemService(Context.AUDIO_SERVICE);
mAudioManagerAudioDeviceCallback = new AudioManagerAudioDeviceCallback();
}
void start() {
mHandlerThread = new HandlerThread("BluetoothActiveDeviceManager");
mHandlerThread.start();
mHandler = new ActiveDeviceManagerHandler(mHandlerThread.getLooper());
IntentFilter filter = new IntentFilter();
filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
filter.addAction(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED);
filter.addAction(BluetoothA2dp.ACTION_ACTIVE_DEVICE_CHANGED);
filter.addAction(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED);
filter.addAction(BluetoothHeadset.ACTION_ACTIVE_DEVICE_CHANGED);
filter.addAction(BluetoothHearingAid.ACTION_ACTIVE_DEVICE_CHANGED);
mAdapterService.registerReceiver(mReceiver, filter);
mAudioManager.registerAudioDeviceCallback(mAudioManagerAudioDeviceCallback, mHandler);
}
初始化 ActiveDeviceManager ,启动 Handler 线程、注册广播、向 AudioManager 注册回调。
该类注释了活跃设备的策略:
3.2.8 SilenceDeviceManager
packages/apps/Bluetooth/src/com/android/bluetooth/btservice/SilenceDeviceManager.java
public class SilenceDeviceManager {
SilenceDeviceManager(AdapterService service, ServiceFactory factory, Looper looper) {
mAdapterService = service;
mFactory = factory;
mLooper = looper;
}
void start() {
mHandler = new SilenceDeviceManagerHandler(mLooper);
IntentFilter filter = new IntentFilter();
filter.addAction(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED);
filter.addAction(BluetoothA2dp.ACTION_ACTIVE_DEVICE_CHANGED);
filter.addAction(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED);
filter.addAction(BluetoothHeadset.ACTION_ACTIVE_DEVICE_CHANGED);
mAdapterService.registerReceiver(mReceiver, filter);
}
}
初始化 SilenceDeviceManager ,启动 Handler 、注册广播。
该类注释了沉默设备的策略:
3.2.9 BluetoothSocketManagerBinder
packages/apps/Bluetooth/src/com/android/bluetooth/btservice/BluetoothSocketManagerBinder.java
class BluetoothSocketManagerBinder extends IBluetoothSocketManager.Stub {
BluetoothSocketManagerBinder(AdapterService service) {
mService = service;
}
}
创建 Socket profile 的 Binder 服务端对象,用于基于蓝牙的 Socket 服务。
3.2.10 invalidateBluetoothCaches
packages/apps/Bluetooth/src/com/android/bluetooth/btservice/AdapterService.java
private void invalidateBluetoothCaches() {
BluetoothAdapter.invalidateGetProfileConnectionStateCache();
BluetoothAdapter.invalidateIsOffloadedFilteringSupportedCache();
BluetoothDevice.invalidateBluetoothGetBondStateCache();
BluetoothAdapter.invalidateBluetoothGetStateCache();
}
以上四个方法调用,全部都是调用同一个方法 PropertyInvalidatedCache.invalidateCache(),仅仅参数不同而已,下面以第一个为例介绍。
frameworks/base/core/java/android/bluetooth/BluetoothAdapter.java
/** @hide */
public static void invalidateGetProfileConnectionStateCache() {
PropertyInvalidatedCache.invalidateCache(BLUETOOTH_PROFILE_CACHE_PROPERTY);
}
frameworks/base/core/java/android/app/PropertyInvalidatedCache.java
public static void invalidateCache(@NonNull String name) {
synchronized (sCorkLock) {
Integer numberCorks = sCorks.get(name);
if (numberCorks != null && numberCorks > 0) {
return;
}
invalidateCacheLocked(name);
}
}
符合要求则更新缓存,该缓存为所有的process共享。
3.2.11 getSharedPreferences
异步初始化,避免 ANR。
3.2.12 setSystemUiUid
packages/apps/Bluetooth/src/com/android/bluetooth/Utils.java
static int sSystemUiUid = UserHandle.USER_NULL;
public static void setSystemUiUid(int uid) {
Utils.sSystemUiUid = uid;
}
缓存 com.android.systemui 进程的 UID,可用于后续判断调用者是否来自该进程。
3.2.13 Set Foreground User
packages/apps/Bluetooth/src/com/android/bluetooth/Utils.java
static int sForegroundUserId = UserHandle.USER_NULL;
public static void setForegroundUserId(int uid) {
Utils.sForegroundUserId = uid;
}
public static final BroadcastReceiver sUserSwitchedReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (Intent.ACTION_USER_SWITCHED.equals(intent.getAction())) {
int fuid = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0);
Utils.setForegroundUserId(fuid);
}
}
};
缓存当前 User 的 UID,可用于后续判断调用者是否来自该进程。
注册了用户变化的广播,用户变化时,更新缓存。
3.3 返回 IBinder 对象
public class AdapterService extends Service {
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
@Override
public void onCreate() {
......
mBinder = new AdapterServiceBinder(this);
......
}
}
返回的对象是 AdapterServiceBinder ,是 IBluetooth.Stub 的子类,对端进程拿到的是其代理对象,用于跨进程通信。