优化android14低内存设备连接蓝牙键盘/鼠标后点击Disconnect断开蓝牙连接,页面卡顿(将1180ms优化到629ms)

目录

1.背景

2.分析

3.解决方案


1.背景

在ST进行测试的过程中,发现在连接蓝牙键盘和鼠标并在设备详情界面断开连接的时候页面有卡顿现象,这里不方便展示,就是在蓝牙的设备详情界面,然后点击断开会有卡顿现象

如下是详细的描述:

在 Android 系统的蓝牙设备详情页(Settings App)中,当我们点击"断开连接(Disconnect)"按钮来断开一个**蓝牙鼠标**时,出现了严重的视觉卡顿:

  1. 手指按下按钮,Material Design 的灰色水波纹(Ripple)刚荡漾出来一半,整个画面瞬间**冻结**。

  2. 画面卡死约 1 秒钟。

  3. 1 秒后,画面恢复,按钮文字突变为"Connect(连接)"。

本文就介绍如何优化这个问题,将蓝牙断开的流程从1180ms优化到629ms,并且解决水波纹卡住问题

2.分析

其实发现在内存低的设备上整体都是比较卡卡的状态,所以有一些稍微更加卡顿的界面就会凸显出来,其实代码都是google的android 14源码,主要就是设备的区别,然后我们来分析下这种问题怎么处理

首先查看日志

日志耗时分析:

开始断开:04-09 20:14:21.610

更新已断开状态:04-09 20:14:21.976

界面刷新:04-09 20:14:22.790

上述进行总结:

点击断开到上层收到状态已断开耗时:366ms

点击断开到界面显示已断开耗时:1180ms

然后我们查询日志中的异常点,如下是在一次断开的流程中相关的异常日志

可以看出来在断开蓝牙的过程中居然界面重新启动了,这肯定是会耗时很多的,然后我们在看看有没有其他异常信息

可以看出来在测试的过程中甚至有掉帧现象,所以肯定是界面显示卡顿的,主线程有时卡顿1秒钟,这肯定肉眼看起来很卡顿

上述我们得到两个信息,

1是鼠标和键盘在断开蓝牙过程中重新启动了Activity

2是由于设备配置太低,主线程已经处理不过来突如其来的大量刷新任务,其实在加日志查看的过程中由于Settings/SystemUI设计的臃肿性导致断开蓝牙后有15个组件一起刷新,所以导致主线程根本处理不过来

3.解决方案

首要解决的就是在断开蓝牙过程中Activity重启现象,在AndroidManifest中对应的Activity添加如下标识符,让其在蓝牙断开连接过程中不会重新启动Activity

android:configChanges="orientation|screenSize|keyboard|keyboardHidden|navigation"

这样我们的耗时过长问题基本解决了,但是发现还是会卡顿,水波纹显示不出来,其实从日志中这时我们从日志中查看onCreate的打印没有了,但是还是会打印出来

Skipped 48 frames! The application may be doing too much work on its main thread.

其实上述虽然我们让其不重新启动了,但是臃肿(15个组件一起更新)的问题还是存在的,所以此时我们需要排优先级,先把点击断开过程的水波纹显示出来,然后开始进行断开流程

这里我们用view.postDelay方式即可

此时优化的差不多了,然后我想进一步优化,就把一些可以放在子线程的方法给放到子线程中了,如下是最终的patch

复制代码
diff --git a/qssi14/frameworks/base/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java b/qssi14/frameworks/base/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
index 803ad1c..848c989 100644
--- a/qssi14/frameworks/base/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
+++ b/qssi14/frameworks/base/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
@@ -50,6 +50,7 @@
 
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.CollectionUtils;
+import com.android.settingslib.utils.ThreadUtils;
 
 import java.lang.reflect.Constructor;
 import java.lang.reflect.InvocationTargetException;
@@ -399,17 +400,19 @@
         }
 
         public void onReceive(Context context, Intent intent, BluetoothDevice device) {
-            if (device == null) {
-                Log.w(TAG, "StateChangedHandler receives state-change for invalid device");
-                return;
-            }
+            ThreadUtils.postOnBackgroundThread(() -> {
+                if (device == null) {
+                    Log.w(TAG, "StateChangedHandler receives state-change for invalid device");
+                    return;
+                }
 
-            CachedBluetoothDevice cachedDevice = mDeviceManager.findDevice(device);
-            if (cachedDevice == null) {
-                Log.w(TAG, "StateChangedHandler found new device: " + device);
-                cachedDevice = mDeviceManager.addDevice(device);
-            }
-            onReceiveInternal(intent, cachedDevice);
+                CachedBluetoothDevice cachedDevice = mDeviceManager.findDevice(device);
+                if (cachedDevice == null) {
+                    Log.w(TAG, "StateChangedHandler found new device: " + device);
+                    cachedDevice = mDeviceManager.addDevice(device);
+                }
+                onReceiveInternal(intent, cachedDevice);
+            });
         }
 
         protected void onReceiveInternal(Intent intent, CachedBluetoothDevice cachedDevice) {
diff --git a/qssi14/packages/apps/Settings/AndroidManifest.xml b/qssi14/packages/apps/Settings/AndroidManifest.xml
index bc116f1..2492c81 100644
--- a/qssi14/packages/apps/Settings/AndroidManifest.xml
+++ b/qssi14/packages/apps/Settings/AndroidManifest.xml
@@ -247,7 +247,8 @@
                   android:exported="false"
                   android:theme="@style/Theme.SubSettings"
                   android:knownActivityEmbeddingCerts="@array/config_known_host_certs"
-                  android:taskAffinity="com.android.settings.root" />
+                  android:taskAffinity="com.android.settings.root"
+                  android:configChanges="orientation|screenSize|keyboard|keyboardHidden|navigation" />
 
         <activity android:name=".Settings$CreateShortcutActivity"
                   android:exported="true"
@@ -4533,6 +4534,7 @@
         <activity android:name="Settings$BluetoothDeviceDetailActivity"
                   android:label="@string/device_details_title"
                   android:exported="true"
+                  android:configChanges="orientation|screenSize|keyboard|keyboardHidden|navigation"
                   android:permission="android.permission.BLUETOOTH_CONNECT">
             <intent-filter android:priority="1">
                 <action android:name="com.android.settings.BLUETOOTH_DEVICE_DETAIL_SETTINGS" />
diff --git a/qssi14/packages/apps/Settings/src/com/android/settings/bluetooth/BluetoothDetailsButtonsController.java b/qssi14/packages/apps/Settings/src/com/android/settings/bluetooth/BluetoothDetailsButtonsController.java
index 2ade4ec..c48c8ee 100644
--- a/qssi14/packages/apps/Settings/src/com/android/settings/bluetooth/BluetoothDetailsButtonsController.java
+++ b/qssi14/packages/apps/Settings/src/com/android/settings/bluetooth/BluetoothDetailsButtonsController.java
@@ -25,6 +25,7 @@
 import com.android.settings.R;
 import com.android.settingslib.bluetooth.CachedBluetoothDevice;
 import com.android.settingslib.core.lifecycle.Lifecycle;
+import com.android.settingslib.utils.ThreadUtils;
 import com.android.settingslib.widget.ActionButtonsPreference;
 
 /**
@@ -72,9 +73,14 @@
                         .setButton2Text(R.string.bluetooth_device_context_disconnect)
                         .setButton2Icon(R.drawable.ic_settings_close)
                         .setButton2OnClickListener(view -> {
-                            mMetricsFeatureProvider.action(mContext,
-                                    SettingsEnums.ACTION_SETTINGS_BLUETOOTH_DISCONNECT);
-                            mCachedDevice.disconnect();
+                            view.postDelayed(() -> {
+                                view.jumpDrawablesToCurrentState();
+                                mActionButtons.setButton2Enabled(false);
+                                ThreadUtils.postOnBackgroundThread(() -> {
+                                    mMetricsFeatureProvider.action(mContext, SettingsEnums.ACTION_SETTINGS_BLUETOOTH_DISCONNECT);
+                                    mCachedDevice.disconnect();
+                                });
+                            }, 150);
                         });
                 mConnectButtonInitialized = true;
             }
相关推荐
shandianchengzi6 小时前
【科普】安卓|安卓手机上如何简便实现Ctrl+Z(需要键盘或一台Windows电脑)
android·windows·智能手机·计算机外设·安卓·科普·记录
nashane14 小时前
HarmonyOS 6学习:外接键盘CapsLock与长截图功能的实战调试与完整解决方案
学习·华为·计算机外设·harmonyos
ACP广源盛1392462567318 小时前
iOS 27 开放 AI 生态@ACP#小型化扩展黄金风口,IX8008全面超越 ASM2806,铸就嵌入式 AI 扩展核心
人工智能·嵌入式硬件·macos·ios·计算机外设·objective-c·cocoa
Jwest20211 天前
工业显示器什么牌子质量最好性价比最高?
计算机外设
hudawei9961 天前
RK R87 Pro AI键盘,AI功能设置与连接教程
人工智能·计算机外设·使用说明·rk r87 ai键盘
byte轻骑兵2 天前
【HID】规范精讲[16]: 蓝牙键盘默认状态玄机——连接中断后,那些设置为何会重置?
人工智能·计算机外设·人机交互·蓝牙键盘·蓝牙鼠标
代码对我眨眼睛2 天前
Mac 如何单独修改鼠标滚动方向,而不影响触控板
macos·计算机外设·策略模式
兴通物联科技2 天前
工业手持终端 PDA 键盘化设计与现场作业效率优化 —— 以 XT8001D 为例
大数据·物联网·计算机视觉·计算机外设·硬件架构
XTIOT6662 天前
工业数据采集设备选型 —— 实体键盘 PDA 的技术优势与场景适配(基于 XT8001D 实践)摘要
大数据·嵌入式硬件·物联网·计算机外设