android 源码分析

10阅读 0评论2024-12-23 iibull
分类:Android平台

10多年没有碰android的源码了, 2010年原来是1.6, 现在都13版本了.
近期发现android 11 版本上的某些PDA机器上存在某个BLE的连接在断开且removeBond后, 后台虽然看不到已绑定设备, 但 getBondState()依然处于bonding状态, 造成 startScan  扫描不到, 而且这种状态都重启PDA或其他方式都无法恢复, 这样在用户创建 createBond就会弹出PIN框.  解决方法只能是由用户手动进行配对连接 或者 {BANNED}中国{BANNED}中国第一次连接后不做removeBond操作.

{BANNED}最佳终解决方法

点击(此处)折叠或打开

  1. <application>
  2. ...
  3. ...
  4.         <receiver android:name="aidc.uhf.pda.args_comm.nls_ble_impl.NlsBlePairReceiver"
  5.             android:exported="true">
  6.             <intent-filter android:priority="1000">
  7.                 <action android:name="android.bluetooth.device.action.PAIRING_REQUEST" />
  8.             </intent-filter>
  9.         </receiver>

  10.     </application>


  11. -------------------------------------------------------
  12. @SuppressLint("MissingPermission")
  13.     @Override
  14.     public void onReceive(Context context, Intent intent) {
  15.         if (BluetoothDevice.ACTION_PAIRING_REQUEST.equals(intent.getAction())) {
  16.             int type = intent.getIntExtra(BluetoothDevice.EXTRA_PAIRING_VARIANT, BluetoothDevice.ERROR);
  17.             //if (type != BluetoothDevice.PAIRING_VARIANT_PIN) return;

  18.             BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
  19.             if (device == null) return;
  20.             String mac = device.getAddress();
  21.             if ((mac == null) || (macPairing == null)) return;
  22.             if (!mac.equals(macPairing)) {
  23.                 LogSdk.e(TAG, "setPin failed: mac not fit macPairing");
  24.                 return;
  25.             }
  26.             String devName = device.getName();
  27.             if ((devName == null) || (devName.length() < 6)) {
  28.                 LogSdk.e(TAG, "Device Name too short. [" + devName + "]");
  29.                 return;
  30.             }

  31.             String szPin = devName.substring(devName.length() - 6);
  32.             boolean bResult = device.setPin(szPin.getBytes()); // 根据规则设定 PIN码
  33.             mBondOK.set((bResult) ? PAIRED_OK : PAIRED_FAILED);
  34.             Log.e(TAG, bResult ? "pairing OK" : "pairing failed");

  35.             abortBroadcast(); // 阻止广播继续传播
  36.         }
  37.     }

  38. 实际上不用 pin 连接, 直接跳过
  39. mBleService = gatt.getService(BT_SERVICE_UUID);// 获取我们的服务的通道.
  40.                if (mBleService != null) {
  41.                    connStatus = BLEDEV_STATE_CONNECTED_AND_PAIRED;
  42. // if (nlsBleSyncPairOnce(mBleDev, TimeoutBlePaired)) { // 根据 PIN码 规则进行 配对
  43. // connStatus = BLEDEV_STATE_CONNECTED_AND_PAIRED;
  44. // LogSdk.w(TAG, "gatt: " + gatt + " mBleGatt: " + mBleGatt);
  45. // } else { //配对失败.
  46. // connStatus = BLEDEV_STATE_INVALID;
  47. // }
  48.                 } else { //未找到专属 service UUID.
  49.                     connStatus = BLEDEV_STATE_INVALID;
  50.                 }

  51. 这样, 后台是 bonding状态, 在进行 connectGatt 时会激发 PIN 提示框, 在 AndroidManifest.xml 中注册了拦截器, 就不会提示了. 然后在连接过程中根本不在进行Bond动作, 这样就可完美避坑

看下android的新版本源码到底哪里有bug造成这个问题. 主要看bluedroid的部分.

下载代码


  1. mkdir /ws/android_11/bin
  2. curl https://storage.googleapis.com/git-repo-downloads/repo > /ws/android_11/bin/repo
  3. chmod a+x /ws/android_11/bin/repo

  4. mkdir /ws/android_11/android-11.0.0_r3
  5. cd /ws/android_11/android-11.0.0_r3

  6. git config --global user.email "iibull@yeah.net"
  7. git config --global user.name "iibull"

  8. /ws/android_11/bin/repo init -u https://aosp.tuna.tsinghua.edu.cn/platform/manifest -b android-11.0.0_r3 --repo-url=https://gerrit-googlesource.lug.ustc.edu.cn/git-repo
  9. repo sync -c --no-tags ## 需要 至少50GB 空间(代码+编译)

点击(此处)折叠或打开

  1. # 初始化编译环境( .可以用source代替,如 source build/envsetup.sh )
  2. . build/envsetup.sh
  3. # 执行
  4. lunch 或者 lunch sdk_phone_x86_64
  5. # 我这里使用模拟器所以选择 31 (即aosp_x86_64-eng)
  6. Which would you like? [aosp_arm-eng] 31
  7. # 开始编译(这里怕我电脑扛不住用的-j1,电脑好的可加大力度)
  8. make -j8 ## 3个小时.


  9. emulator 内存{BANNED}{BANNED}最佳佳好 >= 12GB

点击(此处)折叠或打开

  1. 网上摘录
  2. 安卓中蓝牙协议栈主要分为三个时期,上古时期使用的是BlueZ,后来在4.2之后自己独立出来称为BlueDroid,现在好像又改名叫Fluoride了
  3. BlueZ蓝牙协议栈部分在内核中实现,socket系统调用提供了AF_BLUETOOTH的 family,可以支持获取HCI、L2CAP、RFCOMM类型的socket;

  4. 对于BlueDroid而言,协议栈是在用户层实现的,内核只暴露出HCI(USB/UART)的接口

  5. Android 8.0 以后对蓝牙协议栈进行了重构,主要优化是使用HIDL来取代之前的硬件抽象层,方便厂商的接口集成
  6. /packages/apps/bluetooth/{bluetooth service + profiles}
  7. /packages/apps/bluetooth/jni (bluetooth stack 在 system/bt)通过 HIDL 和 (hardware/interfaces/bluetooth + Vendor impl的Bluetooth Controller)

  8. Android蓝牙协议栈的实现在system/bt目录中.

点击(此处)折叠或打开

  1. 从用户接口出发,参考Android的开发者文档是如何发现设备以及创建蓝牙连接的:

  2. https://developer.android.com/guide/topics/connectivity/bluetooth
  3. https://developer.android.com/guide/topics/connectivity/bluetooth-le

  4. paired和connected的区别:

  5. paired 表示两个设备知道彼此的存在,并且已经协商好了链路秘钥(Link Key),可用该秘钥来进行认证和创建加密链接
  6. connected 表示两个已经配对的设备创建了一个RFCOMM链接,共享一个RFCOMM channel

  7. 其他分析参考 https://evilpan.com/2021/07/11/android-bt/





上一篇:关于放假
下一篇:没有了