記錄android 8設置藍牙名稱的流程。java
packages/apps/Settings/src/com/android/settings/bluetooth/BluetoothDeviceRenamePreferenceController.java 顯示更改框 @Override public boolean handlePreferenceTreeClick(Preference preference) { if (PREF_KEY.equals(preference.getKey())) { mMetricsFeatureProvider.action(mContext, MetricsProto.MetricsEvent.ACTION_BLUETOOTH_RENAME); LocalDeviceNameDialogFragment.newInstance() .show(mFragment.getFragmentManager(), LocalDeviceNameDialogFragment.TAG); return true; } return false; } packages/apps/Settings/src/com/android/settings/bluetooth/LocalDeviceNameDialogFragment.java public class LocalDeviceNameDialogFragment extends BluetoothNameDialogFragment { public static final String TAG = "LocalAdapterName"; private LocalBluetoothAdapter mLocalAdapter; //對話框的title, Rename this device @Override protected int getDialogTitle() { return R.string.bluetooth_rename_device; } 更改確認按鍵在父類中實現。 abstract class BluetoothNameDialogFragment extends InstrumentedDialogFragment implements TextWatcher { @Override public Dialog onCreateDialog(Bundle savedInstanceState) { String deviceName = getDeviceName(); if (savedInstanceState != null) { deviceName = savedInstanceState.getString(KEY_NAME, deviceName); mDeviceNameEdited = savedInstanceState.getBoolean(KEY_NAME_EDITED, false); } // 對話框的顯示已經操做函數。 AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()) .setTitle(getDialogTitle()) .setView(createDialogView(deviceName)) .setPositiveButton(R.string.bluetooth_rename_button, (dialog, which) -> { setDeviceName(mDeviceNameView.getText().toString().trim()); }) .setNegativeButton(android.R.string.cancel, null); mAlertDialog = builder.create(); mAlertDialog.getWindow().setSoftInputMode( WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE); return mAlertDialog; } 設置名稱函數在子類中實現。 packages/apps/Settings/src/com/android/settings/bluetooth/LocalDeviceNameDialogFragment.java protected void setDeviceName(String deviceName) { mLocalAdapter.setName(deviceName); } frameworks\base\packages\SettingsLib\src\com\android\settingslib\bluetooth\LocalBluetoothAdapter.java public void setName(String name) { mAdapter.setName(name); } frameworks\base\core\java\android\bluetooth\BluetoothAdapter.java @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN) public boolean setName(String name) { if (getState() != STATE_ON) return false; try { mServiceLock.readLock().lock(); if (mService != null) return mService.setName(name); } catch (RemoteException e) { Log.e(TAG, "", e); } finally { mServiceLock.readLock().unlock(); } return false; } frameworks\base\core\java\android\bluetooth\IBluetooth.aidl interface IBluetooth { boolean isEnabled(); int getState(); boolean enable(); boolean enableNoAutoConnect(); boolean disable(); String getAddress(); ParcelUuid[] getUuids(); boolean setName(in String name); 對應的服務端程序以下。 frameworks\base\services\core\java\com\android\server\BluetoothManagerService.java case MESSAGE_BLUETOOTH_SERVICE_CONNECTED: { if (DBG) Slog.d(TAG,"MESSAGE_BLUETOOTH_SERVICE_CONNECTED: " + msg.arg1); IBinder service = (IBinder) msg.obj; try { mBluetoothLock.writeLock().lock(); if (msg.arg1 == SERVICE_IBLUETOOTHGATT) { mBluetoothGatt = IBluetoothGatt.Stub .asInterface(Binder.allowBlocking(service)); onBluetoothGattServiceUp(); break; } // else must be SERVICE_IBLUETOOTH //Remove timeout mHandler.removeMessages(MESSAGE_TIMEOUT_BIND); mBinding = false; mBluetoothBinder = service; // 服務端和客戶端創建鏈接 mBluetooth = IBluetooth.Stub.asInterface(Binder.allowBlocking(service)); if (!isNameAndAddressSet()) { Message getMsg = mHandler.obtainMessage(MESSAGE_GET_NAME_AND_ADDRESS); mHandler.sendMessage(getMsg); if (mGetNameAddressOnly) return; } // 客戶端程序繼承IBluetooth.Stub packages\apps\Bluetooth\src\com\android\bluetooth\btservice\AdapterService.java private static class AdapterServiceBinder extends IBluetooth.Stub { private AdapterService mService; public String getName() { if ((Binder.getCallingUid() != Process.SYSTEM_UID) && (!Utils.checkCaller())) { Log.w(TAG, "getName() - Not allowed for non-active user and non system user"); return null; } AdapterService service = getService(); if (service == null) return null; return service.getName(); } // 設置名稱 public boolean setName(String name) { if (!Utils.checkCaller()) { Log.w(TAG, "setName() - Not allowed for non-active user"); return false; } AdapterService service = getService(); if (service == null) return false; return service.setName(name); } boolean setName(String name) { enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission"); return mAdapterProperties.setName(name); } packages\apps\Bluetooth\src\com\android\bluetooth\btservice\AdapterProperties.java boolean setName(String name) { synchronized (mObject) { if (name.length() > BLUETOOTH_NAME_MAX_LENGTH_BYTES) name = name.substring(0, BLUETOOTH_NAME_MAX_LENGTH_BYTES); return mService.setAdapterPropertyNative( AbstractionLayer.BT_PROPERTY_BDNAME, name.getBytes()); } } 調用JNI packages\apps\Bluetooth\src\com\android\bluetooth\btservice\AdapterService.java native boolean setAdapterPropertyNative(int type, byte[] val); packages\apps\Bluetooth\jni\com_android_bluetooth_btservice_AdapterService.cpp static jboolean setAdapterPropertyNative(JNIEnv* env, jobject obj, jint type, jbyteArray value) { ALOGV("%s", __func__); if (!sBluetoothInterface) return JNI_FALSE; jbyte* val = env->GetByteArrayElements(value, NULL); bt_property_t prop; prop.type = (bt_property_type_t)type; prop.len = env->GetArrayLength(value); prop.val = val; int ret = sBluetoothInterface->set_adapter_property(&prop); env->ReleaseByteArrayElements(value, val, 0); return (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; }
Liu Tao
2019-3-27android