- 博客(249)
- 资源 (76)
- 收藏
- 关注

原创 Android-嵌入式蓝牙 多年蓝牙产品开发学习心路历程分享-A2DP音频流的建立、A2DP播放暂停音乐命令交互、HFP、AVRCP、RFCOMM、OPP、AVDTP
序言当你点进来看到这段话的时候,是不是感觉自己被骗了,哈哈哈,本来想搜索蓝牙某个协议,却成了一大段废话文,但此时,别退出去,如果你是一个牛逼的蓝牙开发者,只是想了解蓝牙某个协议或者知识点,那么直接点击进入我的主页,查看蓝牙相关文章,绝对能满足你的需要。但是,如果你是一个蓝牙新人、才开始学习蓝牙开发,那么请用几分钟看完这篇文章,一定会激励你的蓝牙学习和给你提供一个正确的学习途径,废话少说,直入正题。 PS:本文章将持续更新,内容很长,请及时收藏。一、自我介绍1、工作............
2022-05-08 22:23:12
7656
55

原创 Android 蓝牙 A2dp 听歌卡音?audio数据到a2dp通道流程解析----A2dp流控原理(Acl Flow Control),一文搞懂蓝牙卡音问题处理
一、A2dp卡音问题-环境因素先确认问题概率。(低概率则可能为干扰引起,着重关注高概率/必现卡顿问题) 确认是否是共存场景问题。(WiFi/BT共存,a2dp/hid共存等) 确认BT RF是否正常。(NV错误导致卡顿问题) WIFI OTA (WIFI天线和芯片是一起的)指标满足要求。二、传统蓝牙HCI流控(flowcontrol)流控制用于在主机和主机控制器之间,避免传送到主机控制器的未应答远程设备的 ACL 数据溢出主机控制器数据缓冲区。主机(蓝牙协议栈)负责管理主机控制器(蓝牙芯片.
2022-04-26 22:48:19
6137
12
原创 GPS NMEA数据如何看时间?
这是一条标准的 NMEA-0183 协议格式的 GPS 定位数据信息,其中$GPRMC是该语句的标识符,表示推荐最小定位信息(Recommended Minimum Specific GPS/TRANSIT Data)。
2024-12-16 10:03:26
56
原创 Android蓝牙中的Rfcomm协议介绍
RFCOMM(Radio Frequency Communications)是一种基于蓝牙技术的串口仿真协议,以下是详细介绍:一、协议概述二、工作原理三、应用场景
2024-12-12 11:26:36
181
原创 LE Audio基本协议框架
2、控制相关协议,包括MCP、CCP、TBS、CSIS、MICP、VCP、VOCS、AICS等 ,基本是作为控制相关具体协议,例如接听通话、暂停播放音乐、控制音量等。1、基本音频流协议,包括BAP、PACS、ASCS、BASS,功能是建立基本的音频链路连接,音频参数的协商和确认等。3、上层协议,包括CAP、TMAP、PBP、HAP等,负责将子协议组合起来实现具体的应用功能。
2024-12-11 15:14:35
104
原创 Wireshark 使用
PC用wireshark抓包要保证,是PC和设备之间通信,要选择相同的局域网里(不可使用同一局域网下的其他PC进行通信设备之间的抓取)
2024-12-11 11:14:19
48
原创 【Android架构GPS篇】之定位数据如何从GPS芯片到应用层
获取GPS原始数据 Nmea 语句的需要 mLocationManager.addNmeaListener 添加 Nmea 监听,通过相应回调函数获取数据,这个数据中包含原始的 Nmea 数据和平台商自定义的数据,可根据需要自行过滤。onlocationchanged函数。函数:onNmeaMessage。
2024-12-10 15:55:37
80
原创 蓝牙工作原理与发展历程介绍
目前的蓝牙芯片支持多种省电模式,当没有设备连接的时候,几乎是不耗电的,所以手机上的蓝牙开关即使一直开着也不会影响待机时间。由于它和Thread,Zigbee等其他射频技术具有互补特性,市面上也会有几合一版本的SoC解决方案,例如Nordic的nRF52820系统級芯片,具备ARm cortex M4的内核支持,同时支持蓝牙5.2、以及蓝牙mesh、Thread和Zigbee mesh,小型封装提供USB和高级无线连接功能,可用于人机接口设备、智能家居、商业和工业应用。
2024-12-10 14:51:00
110
原创 GPS 问题抓取 log 步骤:提高日志等级
GPS 的 log 与其他模块不同,正常打开开发者模式很多关键类是不会打印log的,需要手动打开手机权限。
2024-12-10 14:43:47
39
原创 GPS测试 QXDM测到的卫星的CN0与看到的CN0不一致
测试GPS功能时,发现通过QXDM工具看到的modem侧的每个卫星的CN0都比手机软件上看到的要低3-3.5db,抓取实时log发现HAL层log打印出来的CN0值就与modem侧不一致。就是说天线和modem侧的CN0会有损耗,大概3.5db左右,HAL层的CN0值是从天线获取的,所以和QXDM看到的有差异。当然也有一些手机平台比较旧,没有合入这个算法,所以看到的CN0是一致的。android log:关键字搜索。
2024-12-10 14:34:07
36
原创 GNSS动态库加载流程举例
这个函数通过规范化路径、比较字符串内容以及验证路径长度和分隔符等一系列操作,严谨地判断一个路径是否是另一个路径的子路径,可用于文件系统相关操作中对路径关系的检查等场景。比如在GNSSProvider初始化时候,要去加载so动态库,如gnsshal->在回到第四步,通过hw_module_exists函数获取GPS库;6、上一步通过指针变量GPS_SO获取到GPSso库名称;1、本文列举GNSS动态so库是如何加载的。()会调用到HAL层;
2024-12-09 17:28:24
32
原创 PassiveProvider GnssLocationProvider、networkProvider、fusedProvider、GeocoderProxy、GeofenceProxy区别
PassiveProvider 定义与工作方式: PassiveProvider 是一种位置提供方式,它本身不会主动发起位置定位请求。它是被动地接收来自其他组件或系统已经获取到的位置更新信息。例如,当其他应用或系统服务(如某个具有主动定位功能的地图应用)已经确定了设备的位置,PassiveProvider 就可以获取这个位置信息并将其提供给需要位置数据的其他应用或模块,自身并不涉及像卫星信号接收、基站定位等主动的定位操作。 应用场景: 主要用于一些不需要主动触发定位,但可以利用其他应用已
2024-12-09 16:28:26
29
原创 传统的控制平面(Control Plane)定位方式是什么
定义与基本原理 控制平面定位是一种在移动通信网络中用于确定移动设备位置的方式。它主要依赖于移动网络的信令和控制机制来实现定位。在移动通信系统的架构中,控制平面负责管理呼叫建立、移动性管理等功能。在定位过程中,利用这些控制功能相关的信息来获取移动设备的位置。 具体而言,当网络需要定位一个移动设备时,它通过移动交换中心(MSC)或者移动管理实体(MME,在 LTE 网络中)等核心网元来触发定位流程。这些核心网元会向基站发送定位请求,基站则利用与移动设备之间的通信链路和相关的信号测量信息来确定设备位置。
2024-12-05 11:42:18
47
原创 Android蓝牙相关日志摘选
logcat2.txt|1854| 10-21 13:18:37.924 6294 6346 V bt_stack: [VERBOSE1:smp_l2c.cc(255)] smp_br_connect_callback for pairing BDA: 28:02:d8:0d:f4:01, pairing_bda:00:00:00:00:00:00 Event: connected //手机临时mac0和设备mac组成acl链路连接完成。
2024-12-05 10:49:40
80
原创 常见的定位方式如:GNSS、Wi-Fi、Bluetooth、基站
卫星定位(以 GPS 为例) 定位原理: GPS 系统由空间部分(卫星星座)、地面控制部分和用户设备部分组成。卫星星座向地球表面发送包含卫星位置、时间戳等信息的信号。用户设备(如 GPS 接收机)接收来自至少 4 颗卫星的信号,通过测量信号传播时间来计算接收机到卫星的距离(由于信号传播速度是光速,根据距离 = 速度 × 时间可计算)。然后,利用三维空间中到多个已知点(卫星)的距离,通过三边测量或多边测量法,解算出接收机在地球上的三维位置(经度、纬度和高度)。 优点: 高精度:在开阔环境下
2024-12-04 19:16:28
56
原创 SUPL(Secure User Plane Location)在GNSS中的作用
SUPL(Secure User Plane Location)的定义 SUPL 是一种在无线通信网络中用于定位的协议。它主要运行在用户平面(User Plane)上,通过移动网络的分组数据通道来传输定位相关的信息,与传统的控制平面(Control Plane)定位方式有所不同。其设计目的是为了在移动设备(如手机等支持 GNSS - 全球导航卫星系统的设备)和定位服务器之间提供一种安全、高效的定位信息交互方式。 SUPL 的工作原理 定位请求阶段:当移动设备(如智能手机)需要进行定位时,它会向网络
2024-12-04 17:43:14
120
原创 GPS历书(Almanac)和星历(Ephemeris)有什么区别?
定义方面 GPS 历书(Almanac) GPS 历书是一种包含了卫星轨道参数的粗略信息的数据集合。它涵盖了所有 GPS 卫星的轨道信息的大致情况,包括卫星的编号、轨道的大致形状(如长半轴、偏心率等大致参数)、卫星信号频率等基本信息。 历书的作用是帮助 GPS 接收机快速地获取卫星的大致位置信息,以便在定位过程中能够初步确定需要搜索和跟踪哪些卫星。例如,当 GPS 接收机首次开机或者长时间未使用后开机时,它可以利用历书信息来快速锁定可能可见的卫星,减少卫星搜索时间。 GPS 星历(Ep
2024-12-04 17:13:38
144
原创 通信之WLAN(Miracast)-RTSP交互
在手机上,该功能被命名为“投屏”,“屏幕投影”,“无线投屏”,“WiFi-Display”等等。在WLAN P2P链路上,WFD设备将建立“UDP”和“TCP”两条网络层的链路,UDP链路用做实时数据流传输,TCP链路承载控制数据流传输。支持Miracast功能的设备,在使用该功能时,可做角色“WFD source”或“WFD sink”(发送端和接收端)。WFD连接过程,如下图4所示。“WFD source”:实时将终端的video和audio(视频和音频)数据传输至WFD sink,如下图2所示。
2024-12-04 14:13:52
72
原创 通信之WLAN(信道)-an\n40h\n40l\u2解释
这个定义挺复杂,我们将WLAN通信系统的信道通俗的解释为“在WLAN通信系统中,信号是用电磁波发射,为了发射端和接收端发送的电磁波彼此可正常接收,指定电磁波发射所用的频段即为信道”。对信道划分介绍时,我们知道相邻的两个信道可扩展为支持40MHz可用带宽。我们先看下WLAN 2.4Ghz对信道的划分,如下图2所示。每个信道的带宽是22MHz,保护间隔1MHz,可用带宽20MHz,不同国家能够使用的信道是不一样的。相邻两个信道可扩展绑定为40MHz,扩展后的信道为(3,4,5,6,7,8,9,10,11)。
2024-12-02 16:57:59
42
原创 Wireshark筛选DHCP包
4、Key type:选择:wpa-pwd;Key:输入路由器的:密码:名称。5、点击OK,即可显示出DHCP流程。wireshark筛选DHCP包。1、编辑-》首选项-》3、点击Edit...
2024-11-26 20:33:50
91
原创 WIFI连接状态有哪个函数打印的?wlan0: State: DISCONNECTED -> INACTIVE
wpa_supplicant_set_state()//当更新状态时候,都是调用这个函数来打印日志;
2024-11-21 11:19:30
28
原创 Wi-Fi 认证-关联-加密流程
WiFi的基于802.11协议进行,无线AP在工作时会定时向空中发送beacon数据包,基站(STA)从beacon中解析出AP的名称、加密方式等信息,从而发起连接。:用于STA;:即刷门禁卡,新生入学,你被分配到97号楼,你提着箱子走到97号楼下想进去,你得有学校给你发的97号楼的门禁卡,证明你是有入住97号楼的资格。同样的,STA想要与AP,也需要一个认证,这就是链路认证;:确定STA有资格和AP建立无线链路后,STA还需要与AP,才能完成无线链路的建立;
2024-11-20 16:52:55
122
原创 wifi物理层和MAC的区别
WiFi 的物理层和 MAC 层是 IEEE 802.11 标准中定义的两个重要层次,它们在功能、实现方式及对 WiFi 性能的影响等方面存在显著区别,以下是具体介绍:
2024-11-13 09:54:39
119
原创 如何从NMEA语句中查看搜星个数
eg1. $GPRMC,220516,A,5133.82,N,00042.24,W,173.8,231.8,130694,004.2,W*70 1 2 3 4 5 6 7 8 9 10 11 12 1 220516 Time Stamp UTC(Coordinated Universal Time)时间,hhmmss(时分秒)格式。根据提供的信息,"$GPGSV,3,2,09,42,,,35,46,,,35,48,,,34,49,,,37,1*6A" 是一个 GPS 定位数据的消息。
2024-11-12 17:37:58
86
原创 omnipeek抓包流程
如果STA解密后,没有dhcp,那就要AP选中,进行解密查看;因为有可能此时只有sta发包或者ap发包,所以筛选时候,只需要刷选一个地址即可,然后解密;,这时候需要抓取空口包来确定本端还是对端问题,今天简单讲解使用omnipeek工具抓包流程;直接点击过滤器,增加一个过滤器(通过wireless address)注意:如果要筛选DHCP,需要确定好STA或者ap地址,然后筛选出来。一般我们处理Wi-Fi断连、耗时长等问题,需要确定是。数据包解密流程(要先stop Capture)然后选中,进行解密;
2024-11-12 17:31:07
77
原创 【Wi-Fi】Short GI 即短保护间隔
在无线通信系统中,特别是基于正交频分复用(OFDM)技术的系统里,GI 是指在每个 OFDM 符号之间插入的一段空白时间间隔,用来避免符号间干扰(ISI)。而 Short GI 则是相对于常规保护间隔而言更短的时间间隔。
2024-11-12 15:30:14
141
原创 256-QAM(Quadrature Amplitude Modulation)是一种数字调制技术,MSC8 和 MSC9 的区别
256-QAM(Quadrature Amplitude Modulation)是一种数字调制技术,MSC8 和 MSC9 可能是指与 256-QAM 相关的不同标准、规范、配置或实现方式等,以下是关于它们之间区别的详细分析:
2024-11-12 15:29:20
48
原创 android蓝牙a2dp协议流程分析(十)--bte_av_media_callback回调赋值
在这个函数中,组装了消息,向btu_task发送BTA_AV_API_REGISTER_EVT事件,同时将我们的回调函数赋值给p_buf->p_app_data_cback,btu_task进程调用对应的处理函数来处理接收到的事件。最后,btu_task进程经过处理,找到bta_av_api_register来处理register事件,在里面我们看到,创建了scb通道句柄,之前也说过,这个句柄是单例的, 也就是生命周期内只有一个,然后进行赋值操作。
2024-02-04 09:03:24
638
1
原创 android蓝牙a2dp协议流程分析(十)--Audio和蓝牙的交互
Audio将要播放的音频数据交给蓝牙协议栈,也就是我们a2dp来进行播放,那么是通过什么将Audio和a2dp连接起来的呢,就是我们的media进程,专门用于发送和接收media数据,在media线程创建了socket,管理socket的文件为UIPC,所以在我们a2dp初始化过程中,使用btif_a2dp_start_media_task函数创建了media线程。在这里,我们创建media线程,在media线程了创建了控制socket,用于Audio和蓝牙之间进行命令的交互,至于数据的通道在后面会说到。
2024-02-02 16:11:02
538
原创 android蓝牙a2dp协议流程分析(九.2)--avdtp协议流程详解之start
btif层状态机的新状态为start,所以调用btif层事件处理函数,也就是btif_av_state_started_handler函数来处理BTIF_SM_ENTER_EVT事件,最终调用到btif_report_audio_state函数。bta_av_proc_stream_evt函数中进行事件转换,将avdt事件转换为bta层事件,发送给到btu_task进程,根据事件类型,我们知道处理该事件的是bta_av_ssm_execute函数。
2024-02-02 16:04:08
312
原创 android蓝牙a2dp协议流程分析(九.1)--avdtp协议流程详解之start
在这个函数中将我们btif层状态机的状态正式切换为open状态,然后向新状态的btif状态机发送BTIF_SM_ENTER_EVT事件,open状态下的btif层事件处理函数是btif_av_state_opened_handler函数,由于这个函数对事件BTIF_SM_ENTER_EVT没有做什么处理,所以我们这里省略。在转换数组中,看到将我们发送的AVDT_OPEN_CFM_EVT事件转换成BTA_AV_STR_OPEN_OK_EVT事件。根据动作选择对应的事件处理函数执行。
2024-02-02 15:54:56
217
原创 android蓝牙a2dp协议流程分析(八.3)--avdtp协议流程详解
当我们调用L2CA_ConnectReq函数向对端蓝牙设备发送连接请求命令建立连接后,对端蓝牙设备返回连接请求的响应消息,这时我们调用之前已经注册的avdt_l2c_connect_cfm_cback回调函数来进行处理,之前也提到过,l2cap通道是先建立,后配置,所以在完成通道的建立以后,调用L2CA_ConfigReq函数来完成l2cap通道的配置。在这个函数中,由于我们现在已经是媒体通道了,所以调用avdt_scb_event函数向scb状态机发送AVDT_SCB_TC_OPEN_EVT事件。
2024-02-02 15:27:01
146
原创 android蓝牙a2dp协议流程分析(八.2)--avdtp协议流程详解
avdt_ccb_event已经介绍过多次,当前ccb状态机的状态为open,所以我们直接来到avdt_ccb_st_open数组中,我们传递过来的event事件为UL_OPEN_EVT,对应要执行的处理函数对应的动作为AVDT_CCB_CHK_TIMER,查阅了一下,这个函数没有什么作用,而ccb状态的下一个状态还是open,没有改变,所有整个这个向ccb状态机发送UL_OPEN_EVT事件没有做什么有用的事件。来到scb的状态转换表中,avdt scb状态机的初始状态为idle。
2024-02-02 15:16:43
211
原创 android蓝牙a2dp协议流程分析(八.1)--avdtp协议流程详解
在这个响应处理函数中,我们调用了之前传递的回调处理函数,也就是bta_av_dt_cback函数集合,也就是里面的bta_av_stream0_cback回调函数,传递的事件为AVDT_GETCAP_CFM_EVTc。当btu_task进程收到bta层的事件后,调用bta_av_hdl_event函数来进行处理,根据事件类型不同,调用不同处理函数,在这里,我们调用的是bta_av_ssm_execute函数来处理。
2024-02-02 15:11:38
209
原创 android蓝牙a2dp协议流程分析(八)--stream control block回调
来到AVDT_CreateStream函数中,在这个函数中为stream control block申请内存空间,传递了我们从bta_av_api_register函数中传递过来的参数cs,这样就把这个参数继续向下进行传输。再avdt_scb_alloc函数中,我们看到了最想看到的,把我们从bta_av_api_register函数中传递的cs参数赋值给到了p_scb的cs成员。在我们后面使用到p_scb->cs.p_ctrl_cback的回调函数以后就知道调用的是哪个回调函数。
2024-02-02 15:03:57
138
原创 android蓝牙a2dp协议流程分析(八)--a2dp协议连接成功后状态回调
在我们a2dp协议的流媒体通道建立后打开后,a2dp连接的最后,调用了btif_av_state_opening_handler函数,在这里调用了btif_report_connection_state函数来进行状态的回调,此时我们的第一个参数state被赋值为BTAV_CONNECTION_STATE_CONNECTED,我们继续往下看。在函数中,由于bt_av_src_callbacks在a2dp初始化的时候被赋值,所以这里调用bt_av_src_callbacks里面对应的回调函数。
2024-02-02 15:00:18
167
Android 蓝牙协议栈消息(bta_sys_sendmsg)发送机制 ---- 全网唯一解析.pdf
2022-05-18
Android 蓝牙BLE全面解析以及智能车锁开发实例
2022-05-09
Android 蓝牙基本概念,每个协议介绍,ble介绍,整理了全网所有的蓝牙基本概念,便于新人学习。
2022-05-08
Android 蓝牙 A2dp 听歌卡音?audio数据到a2dp通道流程解析----A2dp流控原理(Acl Flow Con
2022-05-08
Android 蓝牙 Audio音频输出通道切换详解_卡音,多年安卓开发经验,从实际项目中获取到的经验,对安卓开发者非常有帮助。
2022-05-08
Android 蓝牙 音频焦点(Audio Focus)——卡音,多年安卓开发经验,从实际项目中获取到的经验,对安卓开发者非常有
2022-05-08
Anroid 蓝牙如何在Framework层实现BT的自动配对,多年安卓开发经验,从实际项目中获取到的经验,对安卓开发者非常有帮
2022-05-08
Android 蓝牙OPP 如何正确测量使用蓝牙OPP文件传输时候的电流分析文档,多年安卓开发经验,从实际项目中获取到的经验,对
2022-05-08
Android 蓝牙L2cap协议初始化、连接流程图(协议栈),非常详细的从btif-bta-btm-hci 数据流程走向,以及
2022-04-30
Android 蓝牙map协议连接流程图(上层),将Android 源码使用流程图的形式画了出来,使Android 蓝牙开发者更
2022-04-30
Android pan协议连接流程图,非常详细的从btif-bta-btm-hci 数据流程走向,以及从controller收到
2022-04-30
Android 蓝牙 HFP中的rfcomm数据流程图(协议栈),非常详细的从btif-bta-btm-hci 数据流程走向,以
2022-04-30
Android 蓝牙 HFP中的rfcomm连接流程图(协议栈),非常详细的从btif-bta-btm-hci 数据流程走向,以
2022-04-30
Android 蓝牙 HFP中的rfcomm连接流程图(协议栈),将Android 源码使用流程图的形式画了出来,使Androi
2022-04-30
Android 蓝牙 BLE gatt协议扫描(scan)数据流程图(java-framework),将Android 源码使用
2022-04-30
Android 蓝牙 BLE gatt协议连接(connect)数据流程图(java-framework),将Android 源
2022-04-30
Android 蓝牙 BLE 扫描(scan)数据流程图(协议栈),非常详细的从btif-bta-btm-hci 数据流程走向,
2022-04-30
Android 蓝牙 BLE 连接(connect)数据流程图(协议栈),非常详细的从btif-bta-btm-hci 数据流程
2022-04-30
Android 蓝牙 BLE 广播(advertising)数据流程图(协议栈),非常详细的从btif-bta-btm-hci
2022-04-30
Android 蓝牙 BLE 数据从host发数据到controller,数据流程图(协议栈),非常详细的从btif-bta-b
2022-04-30
Android SDP服务发现初始化、连接流程图(协议栈),非常详细的从btif-bta-btm-hci 数据流程走向,以及从c
2022-04-30
Android 蓝牙PBAP协议连接流程图(java-framework层),将Android 源码使用流程图的形式画了出来,使
2022-04-30
Android 蓝牙hfp连接(java-framework层),非常详细的从btif-bta-btm-hci 数据流程走
2022-04-30
Android 蓝牙HFP 连接、SCO连接流程图(协议栈),非常详细的从btif-bta-btm-hci 数据流程走
2022-04-30
Android 蓝牙HFP 初始化init,协议连接,andio连接,非常详细的从btif-bta-btm-hci 数据流程走
2022-04-30
Android 蓝牙AVRCP(java-framework)层连接流程图,非常详细的从btif-bta-btm-hci 数据流
2022-04-30
Android 蓝牙A2DP java层framework 层连接流程图,非常详细的从btif-bta-btm-hci 数据流程
2022-04-30
Android 蓝牙AVRCP连接流程图(协议栈),非常详细的从btif-bta-btm-hci 数据流程走向,以及从contr
2022-04-30
Android 蓝牙 A2DP协议连接流程图(协议栈),非常详细的从btif-bta-btm-hci 数据流程走向,以及从con
2022-04-30
Android 蓝牙A2DP初始化init流程(协议栈)图,非常详细的从btif-bta-btm-hci 数据流程走向,以及从c
2022-04-30
wifi 回连问题,求解答
2024-03-21
字符设备驱动,指导开发
2024-01-26
wifi断上电回连失败
2023-12-18
(标签-EDGE|关键词-设备树)
2023-08-31
(标签-EDGE|关键词-设备树)
2023-08-31
(标签-EDGE|关键词-设备树)
2023-08-31
(标签-EDGE|关键词-设备树)
2023-08-31
设备树中如何配置电平
2023-08-31
(标签-EDGE|关键词-设备树)
2023-08-31
(标签-EDGE|关键词-设备树)
2023-08-31
(标签-EDGE|关键词-设备树)
2023-08-31
window 平台opengrok搭建
2023-07-20
vs code不能跳转
2023-07-14
TA创建的收藏夹 TA关注的收藏夹
TA关注的人