当前位置: 首页 > article >正文

Android RK356X TVSettings USB调试开关

Android RK356X TVSettings USB调试开关

    • 平台
    • 概述
    • 操作-打开USB调试
    • 实现源码
    • 补充说明

平台

在这里插入图片描述

RK3568 + Android 11

概述

RK3568 是瑞芯微(Rockchip)推出的一款高性能处理器,支持 USB OTG(On-The-Go)和 USB Host 功能。USB OTG 和 Host 的切换功能是 RK3568 的一项重要特性,允许设备在不同的 USB 角色之间动态切换,从而实现更灵活的应用场景。

USB OTG 和 Host 的切换功能

  1. USB OTG(On-The-Go)
    USB OTG 是一种允许设备在主机(Host)和设备(Device)之间动态切换的功能。通过 OTG 功能,RK3568 可以在以下两种模式之间切换:
    • 主机模式(Host Mode):RK3568 作为主机,连接其他 USB 设备(如 U 盘、键盘、鼠标等),并控制数据传输。

    • 设备模式(Device Mode):RK3568 作为从设备,连接到主机(如 PC),被主机控制和数据传输。

  2. 动态切换
    RK3568 支持在运行时动态切换 USB OTG 和 Host 模式,无需重新启动设备或重新插拔 USB 线缆。这种切换功能依赖于硬件设计和软件驱动的支持。


应用场景
USB OTG 和 Host 的切换功能在以下场景中有广泛应用:

  1. 移动设备
    • 在智能手机、平板电脑等设备中,OTG 功能允许用户通过 USB 连接外部设备(如 U 盘、键盘、鼠标等),扩展设备的功能。

    • 例如,用户可以将手机作为主机,连接 U 盘进行文件传输,或者连接键盘和鼠标进行办公。

  2. 嵌入式设备
    • 在嵌入式系统中,RK3568 的 OTG 功能可以用于连接各种 USB 设备,如打印机、摄像头、传感器等。

    • 通过动态切换,设备可以在主机和从机模式之间切换,适应不同的应用需求。

  3. 工业控制
    • 在工业自动化领域,RK3568 可以作为主机连接传感器、控制器等设备,也可以作为从机连接到上位机(如 PC)进行数据采集和监控。

    • 动态切换功能使得设备可以根据任务需求灵活调整角色。

  4. 车载系统
    • 在车载娱乐系统或导航设备中,OTG 功能可以用于连接外部存储设备(如 U 盘)播放媒体文件,或者连接诊断工具进行系统维护。

    • 动态切换功能使得设备可以同时支持多种连接方式。

  5. 物联网设备
    • 在物联网设备中,RK3568 可以通过 OTG 功能连接各种传感器或执行器,实现数据采集和控制。

    • 通过动态切换,设备可以根据网络环境或任务需求调整角色。

  6. 调试和开发
    • 在开发阶段,OTG 功能可以用于连接调试工具(如 JTAG 调试器)或烧录固件。

    • 动态切换功能使得开发者可以方便地在不同模式之间切换,提高开发效率。


技术实现
RK3568 的 USB OTG 和 Host 切换功能依赖于以下硬件和软件支持:
• 硬件支持:RK3568 集成了 USB OTG 控制器,支持动态角色切换。

• 软件驱动:需要操作系统(如 Linux)提供相应的驱动程序和工具,支持 OTG 功能的动态切换。

• 外部电路设计:需要设计合适的 USB 接口电路,支持 OTG 功能(如 ID 引脚检测)。

操作-打开USB调试

设置 > 设备偏好设置 > 开发者选项 > USB 连接状态

在这里插入图片描述

实现源码

packages/apps/TvSettings/Settings/src/com/android/tv/settings/system/development/DevelopmentFragment.java

import com.android.tv.settings.dialog.UsbModeSettings;
/*** Displays preferences for application developers.*/
public class DevelopmentFragment extends SettingsPreferenceFragmentimplements Preference.OnPreferenceChangeListener,EnableDevelopmentDialog.Callback, OemUnlockDialog.Callback, AdbDialog.Callback {private static final String TAG = "DevelopmentSettings";private static final String ENABLE_DEVELOPER = "development_settings_enable";private static final String ENABLE_ADB = "enable_adb";private static final String ENABLE_USB = "enable_usb";//...省略代码...@Overridepublic void onCreatePreferences(Bundle savedInstanceState, String rootKey) {mLogdSizeController = new LogdSizePreferenceController(getActivity());mLogpersistController = new LogpersistPreferenceController(getActivity(), getLifecycle());mUsbModeSetting = new UsbModeSettings(getPreferenceManager().getContext());if (!mUm.isAdminUser()|| mUm.hasUserRestriction(UserManager.DISALLOW_DEBUGGING_FEATURES)|| Settings.Global.getInt(mContentResolver,Settings.Global.DEVICE_PROVISIONED, 0) == 0) {// Block access to developer options if the user is not the owner, if user policy// restricts it, or if the device has not been provisionedmUnavailable = true;addPreferencesFromResource(R.xml.development_prefs_not_available);return;}addPreferencesFromResource(R.xml.development_prefs);final PreferenceScreen preferenceScreen = getPreferenceScreen();// Don't add to prefs lists or it'll disable itself when switched offmEnableDeveloper = (SwitchPreference) findPreference(ENABLE_DEVELOPER);final PreferenceGroup debugDebuggingCategory = (PreferenceGroup)findPreference(DEBUG_DEBUGGING_CATEGORY_KEY);mEnableAdb = findAndInitSwitchPref(ENABLE_ADB);mEnableUsb = findAndInitSwitchPref(ENABLE_USB);mEnableInternetAdb = findAndInitSwitchPref(ENABLE_INTERNET_ADB);mEnableAbc = findAndInitSwitchPref(ENABLE_ABC);mEnableUsb.setChecked(mUsbModeSetting.getDefaultValue());if (mEnableUsb.isChecked()){mEnableUsb.setSummary(R.string.usb_connect_to_computer);} else {mEnableUsb.setSummary(R.string.usb_disconnect_to_computer);}//...省略代码....}

packages/apps/TvSettings/Settings/src/com/android/tv/settings/dialog/UsbModeSettings.java

package com.android.tv.settings.dialog;import com.android.tv.settings.R;import android.content.Context;
import android.os.Handler;
import java.io.File;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import android.os.storage.StorageManager;
import android.os.storage.StorageEventListener;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.SystemProperties;
import android.text.TextUtils;import android.util.Log;public class UsbModeSettings {private static final String TAG = "UsbModeSettings";// 0 otg 1 host 2 peripheralpublic static final String HOST_MODE = new String("host");public static final String SLAVE_MODE = new String("otg");public static final String PROP_FAKE_DATA_ROLE = "persist.fake_data_role";private static final String FILE_NAME_RK3399 = "/sys/kernel/debug/usb@fe800000/rk_usb_force_mode";private static final String FILE_NAME_RK3328 = "/sys/devices/platform/ff450000.syscon/ff450000.syscon:usb2-phy@100/otg_mode";private static final String FILE_NAME_RK3229 = "/sys/devices/platform/11000000.syscon/11000000.syscon:usb2-phy@760/otg_mode";private static final String FILE_NAME_RK356X = "/sys/devices/platform/fe8a0000.usb2-phy/otg_mode";private File file = null;private StorageManager mStorageManager = null;private String mMode = "";private String mSocName = "";private Context mContext;private boolean mLock = false;public UsbModeSettings(Context context) {mContext = context;mSocName = SystemProperties.get("sys.rk.soc");if (TextUtils.isEmpty(mSocName)) {mSocName = SystemProperties.get("ro.board.platform");}if(!TextUtils.isEmpty(mSocName) && mSocName.contains("rk3399")){file = new File(FILE_NAME_RK3399);}else{file = new File(FILE_NAME_RK3328);}file = getFile();mStorageManager = (StorageManager) mContext.getSystemService(Context.STORAGE_SERVICE);boolean ret = checkFile();String mode = ReadFromFile(file);if(ret && !TextUtils.isEmpty(mode)) {mMode = mode;}}private File getFile() {String fileName = FILE_NAME_RK3328;if (!TextUtils.isEmpty(mSocName) && mSocName.contains("rk3399")) {fileName = FILE_NAME_RK3399;} else if (!TextUtils.isEmpty(mSocName) && (mSocName.contains("rk322x") || mSocName.contains("rk3128h"))) {fileName = FILE_NAME_RK3229;} else if (!TextUtils.isEmpty(mSocName) && mSocName.contains("rk356x")) {fileName = FILE_NAME_RK356X;} else {fileName = FILE_NAME_RK3328;}return new File(fileName);}public boolean getDefaultValue() {if (isRk3368()) {//通过prop和init来设置otg模式return getFakeDataRole();}if (checkFile()) {Log.d("UsbModeSelect", "/data/otg.cfg not exist,but temp file exist");if (isRk3368()) {return getFakeDataRole();}if (mMode.equals(HOST_MODE)) {return false;} else {return true;}} else {mMode = HOST_MODE;return false;}}private String ReadFromFile(File file) {if (checkFile()) {try {FileInputStream fin = new FileInputStream(file);BufferedReader reader = new BufferedReader(new InputStreamReader(fin));String config = reader.readLine();fin.close();return config;} catch (IOException e) {Log.i(TAG, "ReadFromFile exception:" + e);e.printStackTrace();}}return null;}private void Write2File(File file, String mode) {if (!checkFile() || (mode == null))return;Log.d("UsbModeSelect", "Write2File,write mode = " + mode);try {FileOutputStream fout = new FileOutputStream(file);PrintWriter pWriter = new PrintWriter(fout);pWriter.println(mode);pWriter.flush();pWriter.close();fout.close();} catch (IOException re) {}}public void onUsbModeClick(String mode) {if (isRk3368()) {setPropFakeDataRole(mode);return;}if (mLock)return;mLock = true;mMode = mode;synchronized (this) {Log.d("UsbModeSettings", "synchronized start");new Thread(mUsbSwitch).start();}}private Runnable mUsbSwitch = new Runnable() {public synchronized void run() {Log.d("UsbModeSettings", "mUsbSwitch Runnable() in*******************");if (mStorageManager != null) {if (mMode == HOST_MODE) {mStorageManager.disableUsbMassStorage();Log.d("UsbModeSettings", "mStorageManager.disableUsbMassStorage()*******************");Write2File(file, mMode);} else {Write2File(file, mMode);Log.d("UsbModeSettings", "mStorageManager.enableUsbMassStorage()  in *******************");mStorageManager.enableUsbMassStorage();Log.d("UsbModeSettings", "mStorageManager.enableUsbMassStorage()   out*******************");}}Log.d("UsbModeSettings", "mUsbSwitch Runnable() out*******************");mLock = false;}};private boolean checkFile() {if (file == null) {Log.e(TAG, "file is null pointer");return false;}String fileName = file.getName();if (!file.exists()) {Log.e(TAG, fileName + " not exist!!!");return false;}if (!file.canRead()) {Log.e(TAG, fileName + " can't read!!!");return false;}if (!file.canWrite()) {Log.e(TAG, fileName + " can't write!!!");return false;}return true;}// 判断是否为3368芯片private boolean isRk3368() {if (!TextUtils.isEmpty(mSocName) && mSocName.contains("rk3368")) {return true;} else {return false;}}private boolean getFakeDataRole() {String fakeDataRole = SystemProperties.get(PROP_FAKE_DATA_ROLE, SLAVE_MODE);Log.d(TAG, "prop fakeDataRole = " + fakeDataRole);if (!TextUtils.isEmpty(fakeDataRole) && fakeDataRole.equals(SLAVE_MODE)) {return true;} else {return false;}}// 将mode转换为Int值,3368的mode为0,1,2private void setPropFakeDataRole(String mode) {Log.d(TAG, "setprop mode = " + mode);SystemProperties.set(PROP_FAKE_DATA_ROLE, mode);}
}

补充说明

  1. 以上源码接口需要system及以上权限
  2. StorageManager部分接口可以通过反射获得.

提取关键代码:

    @Overridepublic void onClick(View v) {StorageManager mStorageManager = (StorageManager) getSystemService(Context.STORAGE_SERVICE);File file = new File(FILE_NAME_RK356X);//切换为 OTG (USB 调试)if(R.id.btOtg == v.getId()) {Write2File(file, SLAVE_MODE);Log.d("UsbModeSettings", "mStorageManager.enableUsbMassStorage()  in *******************");enableUsbMassStorage(mStorageManager);Log.d("UsbModeSettings", "mStorageManager.enableUsbMassStorage()   out*******************");} else if(R.id.btHost == v.getId()) {//切换为HOSTdisableUsbMassStorage(mStorageManager);Log.d("UsbModeSettings", "mStorageManager.disableUsbMassStorage()*******************");Write2File(file, HOST_MODE);}}//写入 USB的模式: otg 或 hostprivate void Write2File(File file, String mode) {if (!new File(FILE_NAME_RK356X).exists() || (mode == null))return;Log.d("UsbModeSelect", "Write2File,write mode = " + mode);try {FileOutputStream fout = new FileOutputStream(file);PrintWriter pWriter = new PrintWriter(fout);pWriter.println(mode);pWriter.flush();pWriter.close();fout.close();} catch (IOException re) {}}//反射接口void enableUsbMassStorage(StorageManager sm){try {Method enableUsbMassStorage = sm.getClass().getMethod("enableUsbMassStorage");enableUsbMassStorage.invoke(sm);} catch (Exception e){e.printStackTrace();}}void disableUsbMassStorage(StorageManager sm){try {Method disableUsbMassStorage = sm.getClass().getMethod("disableUsbMassStorage");disableUsbMassStorage.invoke(sm);} catch (Exception e){e.printStackTrace();}}

相关文章:

Android RK356X TVSettings USB调试开关

Android RK356X TVSettings USB调试开关 平台概述操作-打开USB调试实现源码补充说明 平台 RK3568 Android 11 概述 RK3568 是瑞芯微(Rockchip)推出的一款高性能处理器,支持 USB OTG(On-The-Go)和 USB Host 功能。US…...

CGAL 计算直线之间的距离(3D)

文章目录 一、简介二、实现代码三、实现效果一、简介 这里的计算思路很简单: 1、首先将两个三维直线均平移至过原点处,这里两条直线可以构成一个平面normal。 2、如果两个直线平行,那么两条直线之间的距离就转换为直线上一点到另一直线的距离。 3、如果两个直线不平行,则可…...

消息队列知识点详解

消息队列场景 什么是消息队列 可以把消息队列理解一个使用队列来通信的组件,它的本质是交换机队列的模式,实现发送消息,存储消息,消费消息的过程。 我们通常说的消息队列,MQ其实就是消息中间件,业界中比较…...

序列号绑定的SD卡坏了怎么办?

在给SD卡烧录程序的时候,大家发现有的卡是无法烧录的,如:复印机的SD卡不能被复制通常涉及以下几个技术原因,可能与序列号绑定、加密保护或硬件限制有关: 一、我们以复印机的系统卡为例来简单讲述一下 序列号或硬件绑定…...

使用SystemWeaver生成SOME/IP ETS ARXML的完整实战指南

使用SystemWeaver生成SOME/IP ETS ARXML的完整实战指南 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,可以分享一下给大家。点击跳转到网站。 https://www.captainbed.cn/ccc 一、SystemWeaver与SOME/IP基础认知 1.1 SystemWe…...

基于单片机的BMS热管理功能设计

标题:基于单片机的BMS热管理功能设计 内容:1.摘要 摘要:在电动汽车和储能系统中,电池管理系统(BMS)的热管理功能至关重要,它直接影响电池的性能、寿命和安全性。本文的目的是设计一种基于单片机的BMS热管理功能。采用…...

Flutter 状态管理 Riverpod

Android Studio版本 Flutter SDK 版本 将依赖项添加到您的应用 flutter pub add flutter_riverpod flutter pub add riverpod_annotation flutter pub add dev:riverpod_generator flutter pub add dev:build_runner flutter pub add dev:custom_lint flutter pub add dev:riv…...

【HarmonyOS 5】VisionKit人脸活体检测详解

【HarmonyOS 5】VisionKit人脸活体检测详解 一、VisionKit人脸活体检测是什么? VisionKit是HamronyOS提供的场景化视觉服务工具包。 华为将常见的解决方案,通常需要三方应用使用SDK进行集成。华为以Kit的形式集成在HarmoyOS系统中,方便三方…...

Pycharm(九)函数的闭包、装饰器

目录 一、函数参数 二、闭包 三、装饰器 一、函数参数 def func01():print("func01 shows as follows") func01() # 函数名存放的是函数所在空间的地址 print(func01)#<function func01 at 0x0000023BA9FC04A0> func02func01 print(func02)#<function f…...

【深度学习】详解矩阵乘法、点积,内积,外积、哈达玛积极其应用|tensor系列02

博主简介&#xff1a;努力学习的22级计算机科学与技术本科生一枚&#x1f338;博主主页&#xff1a; Yaoyao2024往期回顾&#xff1a;【深度学习】你真的理解张量了吗&#xff1f;|标量、向量、矩阵、张量的秩|01每日一言&#x1f33c;: “脑袋想不明白的&#xff0c;就用脚想”…...

MH2103系列coremark1.0跑分数据和优化,及基于arm2d的优化应用

CoreMark 1.0 介绍 CoreMark 是由 EEMBC&#xff08;Embedded Microprocessor Benchmark Consortium&#xff09;组织于 2009 年推出的一款用于衡量嵌入式系统 CPU 或 MCU 性能的标准基准测试工具。它旨在替代陈旧的 Dhrystone 标准&#xff08;Dhrystone 容易受到各种libc不同…...

Flowith AI,解锁下一代「知识交易市场」

前言 最近几周自媒体号都在疯狂推Manus&#xff0c;看了几篇测评后&#xff0c;突然在某个时间节点&#xff0c;在特工的文章下&#xff0c;发现了很小众的Flowith。 被这段评论给心动到&#xff0c;于是先去注册了下账号。一翻探索过后&#xff0c;发现比我想象中要有趣的多&…...

策略模式:优雅应对多变的业务需求

一、策略模式基础概念 策略模式&#xff08;Strategy Pattern&#xff09; 是一种行为型设计模式&#xff0c;它通过定义一系列可互换的算法族&#xff0c;并将每个算法封装成独立的策略类&#xff0c;使得算法可以独立于使用它的客户端变化。策略模式的核心思想是 “将算法的…...

SpringBoot企业级开发之【文章分类-新增文章分类】

看一下新增文章的需求&#xff1a; 接口文档&#xff1a; 开发思路&#xff1a; 先在controller下去创建add方法&#xff0c;方法内导入Service类获取add的结果&#xff1b;再在Service接口下去创建add的方法&#xff1b;然后在Service实现类下去实现方法的作用&#xff0c;且导…...

【AI News | 20250421】每日AI进展

AI Repos 1、langgraph-mcp-agents 基于LangGraph的AI智能体系统&#xff0c;集成了MCP&#xff0c;使AI助手能访问各种数据源和API。提供了Streamlit网页界面&#xff0c;方便与LangGraph和MCP工具交互。可以通过界面动态添加、删除以及配置MCP工具&#xff0c;无需重启应用&…...

牛客 | OJ在线编程常见输入输出练习

1.只有输出 言归正传&#xff0c;本张试卷总共包括18个题目&#xff0c;包括了笔试情况下的各种输入输出。 第一题不需要输入&#xff0c;仅需输出字符串 Hello Nowcoder! 即可通过。 #include <iostream> using namespace std; int main(){string s "Hello Nowco…...

python生成动态库在c++中调用

一.Windows下生成动态库.pyd 在setup.py的同目录下使用python setup.py build_ext --inplace 二.在vscode的c中使用.pyd文件&#xff08;动态库&#xff09; 1&#xff09;配置python的环境 python -c "import sys; print(sys.executable)" #确定python安装位置 2…...

程序员学商务英文之Terms of Payment Packing

Dia-3: Packing 1 包装-1 1. I’m here to improve my communication skill of English. 我来这里是为了提升我的英文沟通技能。 2. What a co-incidence! Fancy meeting you here. 这么巧&#xff01;真没想到在这见到你。 3. Some birds aren’t meant to be caged…...

OpenCV基础函数学习4

【大纲笔记见附件pdf】 目录 一、基于OpenCV的形态学操作 二、基于OpenCV的直方图处理 三、基于OpenCV霍夫变换 四、基于OpenCV模板匹配 一、基于OpenCV的形态学操作 二、基于OpenCV的直方图处理 三、基于OpenCV霍夫变换 四、基于OpenCV模板匹配...

Nginx反向代理用自定义Header参数

【啰嗦两句】 也不知道为啥&#xff0c;我仅仅想在Nginx的反向代理中使用自己定义的“x-api-key”做Header参数&#xff0c;却发现会被忽略&#xff0c;网上搜的资料都是说用“proxy_set_header”&#xff0c;却只愿意介绍最基本的几个参数&#xff0c;你懂的&#xff0c;那些资…...

详解机器学习各算法的优缺点!!

在机器学习这个 “工具库” 里&#xff0c;算法就像各种各样的工具&#xff0c;每一种都有自己的 “脾气” 和 “特长”。有些算法擅长找规律&#xff0c;有些算法能快速分类&#xff0c;还有些在处理复杂数据时特别厉害。 而且&#xff0c;就像锤子适合敲钉子、螺丝刀适合拧螺…...

Manus AI与多语言手写识别

一、手写识别技术的发展历程 1.1 早期的手写识别技术 手写识别技术起源很早&#xff0c;1929年德国人Tausheck就取得了相关专利。早期主要采用模板匹配等方法&#xff0c;该方法需准备字符模板库&#xff0c;提取待识别字符特征后进行匹配。但其局限性明显&#xff0c;对字符…...

C++23 让 Lambda 表达式中的 () 更可选:P1102R2 提案深度解析

文章目录 一、背景与动机&#xff1a;Lambda 表达式中的痛点1.1 问题的根源 二、P1102R2 提案&#xff1a;让 () 可选2.1 提案的核心内容2.2 语法调整的细节2.3 提案的合理性 三、编译器支持&#xff1a;主流编译器的跟进四、对 C 编程的影响&#xff1a;简化语法与提升一致性4…...

规则引擎 - Easy Rules

Easy Rules 依赖demodemo1demo2 总结 Easy Rules 是一个轻量级的 Java 规则引擎&#xff0c;使用简单&#xff0c;适合快速开发和简单的规则场景&#xff0c;适合对于一些判断&#xff0c;是否属于白名单&#xff0c;是否有特殊权限&#xff0c;是否属于当前区域&#xff0c;调…...

3步拆解Linux内核源码的思维模型

3步拆解Linux内核源码的思维模型 ——从“不敢碰”到“庖丁解牛” 一、第一步&#xff1a;资料收集与框架搭建——像拼图一样找到“地图” 初看Linux内核源码的人&#xff0c;往往会被其千万行代码淹没。但正如登山前需要地形图&#xff0c;阅读内核前必须构建认知框架。 1…...

MyBatis与MyBatis-Plus:字段自动填充的两种实现方式

目录 1. 使用 MyBatis 拦截器实现字段自动填充 2. 使用 MyBatis-Plus 实现字段自动填充 1. 使用 MyBatis 拦截器实现字段自动填充 实现步骤 创建拦截器 实现 MyBatis 的 Interceptor 接口&#xff0c;通过拦截 MyBatis 执行的 SQL 操作来自动填充公共字段 Intercepts({Signa…...

深度学习:人工智能的核心驱动力

深度学习 在当今科技飞速发展的时代&#xff0c;人工智能&#xff08;AI&#xff09;无疑是最具影响力和变革性的技术之一。而深度学习&#xff0c;作为人工智能领域的核心技术&#xff0c;正以其强大的能力和广泛的应用&#xff0c;深刻地改变着我们的生活和世界。深度学习究竟…...

Java学习路线--自用--带链接

1.Java基础 黑马&#xff1a;黑马程序员Java零基础视频教程_下部 2.MySQL 尚硅谷&#xff1a;MySQL数据库入门到大牛&#xff0c;mysql安装到优化&#xff0c;百科全书级&#xff0c;全网天花板 3.Redis 黑马&#xff1a;黑马程序员Redis入门到实战教程&#xff0c;深度透…...

在Qt中验证LDAP账户(Windows平台)

一、前言 原本以为在Qt&#xff08;Windows平台&#xff09;中验证 LDAP 账户很简单&#xff1a;集成Open LDAP的开发库即可。结果临了才发现&#xff0c;Open LDAP压根儿不支持Windows平台。沿着重用的原则&#xff0c;考虑迁移Open LDAP的源代码&#xff0c;却发现工作量不小…...

【sylar-webserver】重构日志系统

文章目录 主要工作流程图FiberConditionBufferBufferManagerLogEvent 序列化 & 反序列化LoggerRotatingFileLogAppender 主要工作 实现&#xff0c; LogEvent 序列化和反序列化 &#xff08;使用序列化是为了更标准&#xff0c;如果转成最终的日志格式再存储&#xff08;确…...