Android手机底层软硬件

Android多媒体功能开发(14)——Camera2框架 Camera2框架的相机模型被设计成一个管道,使用相机时需要先和相机设备建立一个会话,通过该会话向相机发送请求,相机将图像数据保存到配置好的Surface,Surface就是存放图像数据的缓冲区。请求分为单次请求、重复请求和多次请求三种。 阅读详情

Android底层软硬件结合开发概述

Android是 个开源的智能移动平台 一个开源的智能移动平台, 任何 个厂商拿 一个厂商拿到 Android Source 都可以基于自己的硬件架构设计

移动设备。

硬件多样化

厂商自己的利益

软硬件结合开发的弊端?

失去了Android应用的跨平台特性

由于不同厂商研发能力参差不齐,应用程序的稳定性及性能有所不同

分类

NDK开发:

从应用角度来开发软硬结合代码

适用于单个应用程序的底层结合需求

HAL硬件抽象层开发:

从整个系统框架需求角度来开发本地程序

适用于共享功能软硬结合代码


HAL 概念

HAL( Hardware Abstract Layer)硬件抽象层是Google开发的Android系统里上层应用对底层硬件操作屏蔽的一个软件层次,说白了,就是上层的应用不用关心底层硬件具体是如何工作的,只要向上提供一个统一的接口即可,这种设计思想广泛的存在于当前的软件架构设计里。

image-20200706134655889

image-20200706134701523

image-20200706134709193

image-20200706134718998

image-20200706134646845

HAL存在的原因

1、 并不是所有的硬件设备都有标准的 linux kernel 的接口。

2、 Kernel driver涉及到GPL的版权。某些设备制造商并不愿意公开硬件驱动,所以才通过HAL方式绕过GPL。

3、 针对某些硬件, Android有一些特殊的需求。

HAL简介及现状分析

现有HAL架构由 Patrick Brady (Google) 在2008G l oogle I/O演讲中提出, 从上面架构图我们知道,HAL 的目的是为了把 Android framework 与Linux kernel 完整「隔开」。让 Android 不至过度依赖 Linux kernel, 有点「kernel independent」的意思。

AL简介及现状分析

HAL 主要的实现储存于以下目录

libhardware_legacy/ ‐ 旧的架构、 采取链接库模块的观念进行

libhardware/ ‐ 新架构、调整为 HAL stub 的观念

旧的HAL 架构(libhardware_legacy)

libhardware_legacy 作法,是传统的「module」方式,也就是将 *.so 文件当做「shared library」来使用,在runtime(JNI 部份) 以 direct functioncall 使用 HAL module。通过直接调用函数的方式,来操作驱动程序。

当然,应用程序也可以不需要通过 JNI 的方式进行, 直接加载 .so 库(dlopen)的做法调用.so 里的符号(symbol)也是 一种方式。

总而言之是没有经过封装,上层可以直接操作硬件。

image-20200706134945797

image-20200706135452501

新的HAL 架构(libhardware)

现在的 libhardware 架构,就有「stub」的味道了。 HAL stub 是一种代理人(proxy) 的概念, stub 虽然仍是以 *.so的形式存在,但 HAL 已经将 *.so 隐藏起来了。 Stub 向 HAL「提供」 操作函数(operations) ,而 runtime 则是向 HAL 取得特定模块(stub)的 operations,再 callback这些操作函数。 这种以 indirect function call 的架构,让HAL stub 变成是一种「包含」关系,即 HAL 里包含了许许多多的 stub(代理人) 。Runtime 只要说明「类型」,即module ID,就可以取得操作函数。

对于目前的HAL, 可以认为Android定义了HAL层结构框架,通过几个接口访问硬件从而统一了调用方式。

image-20200706135547846 image-20200706135611185

HAL_legacy和HAL的对比

  • HAL_legacy:旧式的HAL是一个模块,采用共享库形式,在编译时会调用到。 由于采用 function call 形式调用,因此可被多个进程使用,但会被 mapping 到多个进程空间中, 同时需要考虑代码能否安全重入的问题(thread safe)。

  • HAL: 新式的HAL采用 HAL module 和 HAL stub 结合形式,HAL stub不是一个share library,编译时上层只拥有访问HAL stub的函数指针, 并不需要HAL stub。 上层通过HAL module提供的统一接口获取并操作HAL stub,so文件只会被mapping到一个进程, 也不存在重复mapping和重入问题。

HAL_legacy和HAL的对比

Module

角色是被调用 , 在Android架构里面仅作为程序库(library)用途

Stub

Stub又称为代理人(proxy) , 扮演操作供应者的概念(operations provider)

HAL_legacy和HAL的对比

HAL stub的框架比较简单: 三个结构体、 两个常量、 一个函数

它的定义在:

hardware/libhardware/include/hardware/hardware.h
hardware/libhardware/hardware.c  

HAL Stub架构分析

/*
每个一个HAL Stub都通过 hw_module_t 来描述, 我们称之为一个Stub对象。你可以去“ 继承 ”这个 hw_module_t,然后扩展自己的属性,这个HAL Stub对象必须定义为一个固定的名字:HMI( Hardware Module Information ) ,每一个Stub对象里都封装了一个函数open,通过这个函数来打开这个硬件Stub设备,返回这个硬件对应的Operation interface。
*/
struct hw_module_t;
/*
HAL Stub对象的open描述结构体, 它里面只有一个元素: open函数指针
*/
struct hw_module_methods_t;

/*
由结构体hw_module_t可知,它的open函数返回一个硬件对应的Operation interface, 这个硬件的operation interface的描述由hw_device_t 结构体来描述
*/
struct hw_device_t;
// 这个就是HAL Stub对象固定的名字
#define HAL_MODULE_INFO_SYM	HMI
// 这个是以字符串的名字
#define HAL_MODULE_INFO_SYM_AS_STR "HMI"
//这个函数是通过硬件名来获得硬件HAL Stub对象
int hw_get_module(const char *id, const struct hw_module_t **module);
//注册一个Stub对象
const struct led_modulet_HAL_MODULE_INFO_SYM = {
    common: {
    tag: HARDWARE_MODULE_TAG,
    version_major: 1,
    version_minor: 0,
    id: LED_HARDWARE_MODULE_ID,
    name: "led HAL Stub",
    author: "farsight",
    methods: &led_module_methods,
    },
    // 扩展属性放在这儿
}

image-20200706135929366

image-20200706135949036


Android里的Jni调用机制

JVM 很好的解决java的可移植性问题,使得java软件可以在不同的硬件平台下运行,但是JVM不是万能的,毕竟它只是一个模拟环境,对于一些外围的硬件就很难模拟, JVM只是模拟了一部分的寄存器, 栈结构, JVM储存器,这些都是软件运行的基础硬件结构。

对于像android手机这样的平台, 有很多的外围设备在软件层是需要操作的,如wifi,蓝牙,触摸屏,重力感应,键盘等,如果直接通过java语言操作是很难实现的, JVM无法模拟这些硬件。

JNI( Java Native Interface ), 中文为JAVA本地调用。 从Java1.1开始,Java Native Interface( JNI )标准成为java平台的一部分,它允许Java代码 和 其他语言写的代码进行交互。 JNI一开始是为了本地已编译语言, 尤其是 C 和 C++ 而设计的,但是它并不妨碍你使用其他语言,只要调用约定受支持就可以了。使用 java 与本地已编译的代码交互,通常会丧失平台可移植性。

但是, 有些些情况下这样做是可以接受的, 甚至是必须的,比如, 使用一些旧的库,与硬件、操作系统进行交互,或者为了提高程序的性能。 JNI标准至少保证本地代码能工作在任何Java虚拟机实现下。

image-20200706140038704

Jni在 Java和C、 C++等语言之间建立了一个桥梁作用,因此, JNI首先要做的,就是统一两者间的数据类型。

所有其它引用类型,在JNI中都被定义为 jobject 类型,在C中都定义为 void*。

Java Language TypeJNI Type
booleanjboolean
bytejbyte
charjchar
shortjshort
intjint
longjlong
floatjfloat
doublejdouble

Java中可以直接调用底层语言的函数或方法, Jni规定了Java调用底层语言的方法签名规范。

类型签名Java 类型类型签名Java 类型
Zboolean[[]
Bbyte[Iint[]
Cchar[Ffloat[]
Sshort[Bbyte[]
Iint[Cchar[]
Jlong[Sshort[]
Ffloat[Ddouble[]
Ddouble[Jlong[]
Lfully-qualified-class(全限定的类)[Zboolean[]

Android里的Jni调用机制

  • 函数签名通常是以下结构: 返回值 fun(参数1,参数2,参数3) ;

  • 其对应的Jni方法签名格式为: (参数1参数2参数3)返回值

  • 注意:

函数名,在Jni中没有体现出来

参数列表相挨着, 中间没有逗号, 没有空格

返回值出现在()后面

如果参数是引用类型, 那么参数应该为: L类型;

HAL Led调用流程

/LedDemo/Led Service(java)/Led Service(Native)/Led HAL Stub1:创建服务对象<<create>>2:通过JNI初始化本地服务()3: 查找并得到HAL操作接口()4:返回device操作接口5:操作service提供的API()6: 通过JNI调用本地服务操作接口()7: 调用保存的devicer操作接口()8: 返回HAL操作结果9: 返回本地服务操作结果10: 返回框架服务操作结果/LedDemo/Led Service(java)/Led Service(Native)/Led HAL Stub
/Led APP/Led Service(java)/Led Service(Native)/Led HAL Stub1:new LedService()2:system.loadLibrary()3: JNI_OnLoad()注册java方法与本地函数的映射关系4: _init()5: hw_get_module()6: Return module_t object7: callback module_t open interface()8: Return device_t operations9: LedService.set_on/set_off()10: _set_on, _set_off()11: devict_t->>set_on/set_off()/Led APP/Led Service(java)/Led Service(Native)/Led HAL Stub
用C在安卓手机上开发 在安卓手机上进行C语言开发需要一些特定的工具和设置。通常,C语言用于编写安卓的底层代码,如性能关键的模块或与硬件直接交互的部分。我们可以使用Android NDK(Native Development Kit)来开发这些部分。以下是如何在安卓手机上使用C进行开发的详细步骤。 阅读详情

相关推荐

在Mac上使用android studio调试android手机

一.环境准备 1.安卓手机:Android版本为9 2.MacBook Pro 3.安卓数据线 二.adb介绍 1.adb概念 adb:全称是Android Debug Bridge,意思是Android调试桥,一个开发工具,主要用于PC端和Android设备调试连接通信的作用。 从最早的Eclipse到现在的Android Studio,其实底层和Android设备的连接,都是依赖的adb去做的。 这种通信大多是在USB电缆下进行,但是也支持Wi-Fi连接。 adb 还可被用来与电脑上运行的安卓模拟器交流

鸡排小农的博客 4214

Android底层技术:Java层系统服务(Android Service)

为什么我们需要学习撰写系统服务呢? 底层系统服务是Android 框架裡接近Linux/Driver 的部分。为了充分发挥硬件设备的差異化特性,系统服务是让上层Java 应用程序來使用Driver/HW Device 特色的重要管道。于此,先仔细解析Java层系统服务的架构,然后阐述这系统服务的代码开发要点,以及其API设计方法。

导出手机apk底层数据库

导出手机apk底层数据库 一、背景说明     据我调查,导出手机apk数据主要有两种方法:root方法和非root方法。我的硬件是小米4手机,Windows7环境,导出小米运动数据,华为手机底层数据库有一些是加密的,用代码可以查看。 二、非root方法 首先讲一下root的方法,root完手机后,可以下载一个RE文件管理器,便可以从data/data/目录下查看各APP的底层文件了。

Bruce_1992的博客 2925

Android底层软硬件结合开发

Android是 个开源的智能移动平台 一个开源的智能移动平台, 任何 个厂商拿 一个厂商拿到 Android Source 都可以基于自己的硬件架构设计移动设备。硬件多样化厂商自己的利益软硬件结合开发的弊端?失去了Android应用的跨平台特性由于不同厂商研发能力参差不齐,应用程序的稳定性及性能有所不同分类NDK开发:从应用角度来开发软硬结合代码适用于单个应用程序的底层结合需求HAL硬件抽象层开发:从整个系统框架需求角度来开发本地程序适用于共享功能软硬结合代码。

实力派,无需多言! 1524

Android系统概述——底层开发的资料

Android系统概述——底层开发的资料 Android系统概述——底层开发的资料

免root实现 Android改机(一键新机)技术解密。

此篇文章仅探讨Android底层技术。不提供任何软件和安装包…… 我们通过一些底层技术对手机中的各种基础信息进行一个修改。 举例说明:主要修改的参数有: Android_Id、IMEI、手机序列号、手机号码、WIFI-MAC、WIFI-Name、安卓系统版本、ROM固件、手机号码、手机型号、手机品牌、CPU型号、手机制造商、GPS定位、通话记录模拟、手机短信模拟…… 等各类安卓手机系统信息的修改功能。 举例子:统改机方式,使用xposed的代码: HTool.XHookMethod(android.telephony.TelephonyManager.class.getName(),mLp

12月26日,唐攀网络直播讲解《Android手机底层软硬件结合开发技术》

唐攀 华清远见高级讲师,高级嵌入式软件工程师。从事多年知名外企嵌入式方向软件研发,拥有丰富的项目经验。擅长ARM体系结构及接口编程,Linux驱动开发,Linux下C语言编程,Android系统移植与优化,著有《深入浅出:嵌入式底层软件开发》等书籍,目前专注于嵌入式移动平台系统领域,参与社区医疗终端系统等多个移动应用项目,从事平板电脑移植与优化,智能家居系统等研发工作.有着丰富的高校师资培训和an

华清远见 | 程序员的学习天堂 2483

深入解析ACS SPiiPlus运动控制器的托管API架构与实战应用

本文深入解析了ACS SPiiPlus运动控制器的托管API架构,详细介绍了其核心模块、设计哲学与实战应用。通过C#/.NET封装的托管接口,开发者能够高效实现多轴协同运动控制、EtherCAT总线集成以及事件驱动的异步编程,显著提升高精度工业自动化设备的开发效率与系统稳定性。

jwt8token的博客 862

鸿蒙系统100万台手机测试,100万台手机测试鸿蒙系统,解决安卓碎片化,流畅度不输ios!...

导语:100万台手机测试鸿蒙系统,解决安卓碎片化,流畅度不输ios!华为鸿蒙系统已在100万台手机上测试,改变安卓系统的碎片化问题,是不是就不卡了?如果鸿蒙系统像麒麟芯片那样只给华为手机用的话,相信碎片化程度肯定会远远低于安卓系统,安卓作为开放性系统最大的诟病就是复杂的适配环境,需要照顾到成百上千种手机产品,再加上数不清的各类APP,因此优化和适配起来相当困难,碎片化从安卓系统开始流行就伴随到今天...

weixin_39602108的博客 463

A robust and easy to implement method for IMU calibration without external equipments(IMU标定)

A robust and easy to implement method for IMU calibration without external equipments 1 标定原理1 亲试可用,还有动态演示效果不错。相比商用产品的简易标定流程,该标定方法有以下几点不同: 给出了加速度计和陀螺仪更复杂的模型。 利用Allan方差的定义,标定陀螺仪的偏置。 大量冗余数据,保证最优化收敛。利用数十...

擦擦擦大侠的博客 3950

ArcGIS基础:CAD数据转换为GIS数据(符号化显示、数据转换、线转面、空间连接)

1、符号化显示: CAD数据加载进来有很多列表,包含了点【point】、线【polyline】、面【polygon】、标注数据【Annotation】等数据,本次实验我们需要用到的是面数据,也就是.dwgPolygong格式的数据。如下图所示: 把数据加载进来,然后在2处打开属性表,查看CAD数据的属性表,打开后可以发现【layer】图层表示就是地块的用地性质,它就是符号化显示的依据。 我们在数据上右键【属性】,打开图层属性,找到【符号系统】,选择类别中的【唯一值】,然后在【值字段】下拉选择【layer】,

yuanYW7556的博客 2万+

高通Android手机软件开发培训

      为期两天的高通Android手机软件开发培训结束了。这次高通针对QSC7x27/7x25/QSD8x50的基带芯片进行了两天的Android手机软件开发培训。参加人员都是我这样的各个OEM厂商的软件开发人员。这次难得的机会是我转到底层驱动开发以来,自己争取的。本来安排的两个人都没有空,只有我这个新丁有空闲来。正好这次的基带芯片都是双核的,我们现在手头上也在做着双核的项目,我也有幸参

bengold1979的专栏 5908

eICU数据库没有ventilation_event表

各位学友大家好,我是环湖医院神经外科的飞时过,很多外院的老师和我问,ventilation_event表的问题,哪怕用ChatGPT也无法正确生成,今天我给大家用SQL做一个拿来就能用的。

环湖数据科学知识共享平台 939

小米手机测试笔试题深度解析:从Android底层到硬件实战

在移动互联网时代,手机测试是连接软硬件体验与用户感知的关键环节,其核心在于建立系统性的测试思维框架。从Android系统架构与进程管理,到屏幕、电池等硬件参数解读,再到性能、功耗、稳定性等专项测试方法,手机测试工程师需要掌握一套复合型知识体系。本文以小米秋招手机测试笔试题为例,梳理了测试用例设计、Bug生命周期管理、兼容性矩阵等工程实践要点,并重点解析了性能测试中帧率与卡顿率的量化分析、功耗测试中的电流拆解思路,以及蓝牙类问题的分层排查方法。通过剖析典型笔试题的命题逻辑与答题技巧,帮助读者理解从基础理论到真

weixin_34302798的博客 385

SAP SD跨公司销售IDOC自动记账配置实战指南

本文详细介绍了SAP SD模块中跨公司销售IDOC自动记账的配置实战指南。通过IDOC技术实现集团企业间交易的自动化处理,显著提升财务效率和准确性。文章涵盖前置配置、RFC连接、合作伙伴参数设置及财务科目分配等关键步骤,并提供了常见错误排查和性能优化建议,帮助用户快速掌握这一高效业务流程。

weixin_29284885的博客 772

有限状态机FSM详解(一)

有限状态机在维基百科中的解释是: 有限状态机(英语:finite-state machine,缩写:FSM)又称有限状态自动机,简称状态机,是表示有限个状态以及在这些状态之间的转移和动作等行为的数学模型。 至于为什么要学FSM,FSM可以把模型的多状态、多状态间的转换条件解耦。可以使维护变得容易,代码也更加具有可读性,也更加艺术。 理解有限状态机首先需要理解整个模型。我们把灯的开关作为示例,...

benjonc的博客 5万+

手机系统制作:从底层逻辑到前沿重构

加之不同CPU架构的启动入口差异、海量设备的驱动兼容以及复杂的多线程并发同步机制,使得从零构建一个工业级的手机系统变得异常困难。以华为为例,为了解决安卓系统长期使用后的卡顿痛点,其团队曾成立特战组,从系统松散管理、硬件资源协同等底层逻辑入手,推出方舟编译器,对安卓进行深度优化。传统的操作系统资源调度是围绕“人操作应用”来设计的,而新一代的智能体原生操作系统(如Step AOS)则选择从零重构底层框架,以服务AI智能体的运行为核心。面对巨大的技术壁垒,手机系统的制作衍生出了多种不同深度的实践路径。

yangmu3203的博客 253

Jetson Nano之CSI摄像头操作方法

jetson端csi摄像头的应用方法

ZONGXP的博客 1万+

怎么看手机android底层,安卓手机中fastboot是一种比recovery更底层的模式

该楼层疑似违规已被系统折叠隐藏此楼查看此楼1 手机进入fastboot需要一定的操作才能进入,尤其是没刷过机的情况下2 先说刷过机的,如果刷过机,root过,一般民间自制的ROM都会有重启的选项,按电源键重启,选择重启到fastboot即可3 没刷过机的则需要按组合键进入fastboot。首先先关机,在关机状态下按组合键即可直接进入fastboot。不同手机进入fastboot的组合键不同,如H...

weixin_29763721的博客 1412

福建公共资源交易平台 portal-sign与响应Data解密逆向实录

本文分析了福建公共资源交易电子公共服务平台的接口加密机制。通过抓包和代码分析,发现请求头中的portal-sign由MD5算法生成,包含固定秘钥和排序后的参数拼接。响应数据采用AES-256-CBC加密,需使用特定Key和IV解密。文章详细介绍了签名生成规则、参数处理流程及加密常量定位方法,为接口对接提供了技术参考。整个过程展示了如何通过逆向工程还原前端加密逻辑,最终实现脱离浏览器环境的纯协议调用。

自成背后的博客 1160

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

鸿蒙ArkTS 与安卓Android-底层逻辑对比

总体来说,鸿蒙OS在设计上更注重跨设备和跨平台的无缝协作,底层架构采用微内核来提高安全性和灵活性;而安卓系统则基于Linux内核,构建了一个成熟的移动设备操作系统,专注于智能手机、平板等设备。

yuwinter的博客 2395

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

android 手机 优化,安卓手机超级优化技巧,流畅度飙升50%

原标题:安卓手机超级优化技巧,流畅度飙升50%很多人对于“安卓优化”的概念,还停留在root、清理内存、精简系统等老一套。而如今安卓手机存储和内存都已经大幅提升,这些旧方法对于流畅度的提升很不明显。那有什么技巧可以让安卓手机运行的更快呢?笔者为大家介绍一个优化神技。 不过,在正式介绍之前,大家首先需要明白安卓为何不如iPhone流畅。抛开低配的千元机不谈(硬件性能差异实在太大),许多安卓手机的参数...

weixin_32146783的博客 3913

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

一张图看懂虚拟安卓手机与真机的底层区别

虚拟是模拟手机,而真机才是实机。在需要真实稳定环境的业务中,真机阵列是唯一长期可靠的方案。

m0_57142664的博客 599

华为android底层,华为对安卓底层更新再进一步,EMUI 11曝光,将落户华为Mate 40!...

原标题:华为对安卓底层更新再进一步,EMUI 11曝光,将落户华为Mate 40!对于智能手机厂商来说,2020年是一个特殊的节点。它不仅标志着5G的大规模席卷,也意味着这是一个新十年的开始,即使当前困难重重,各大智能手机厂商都希望能够在这一年中交出一份满意的答卷。而作为智能手机的灵魂,安卓操作系统在国内智能手机市场上一直都是“一统天下”的,不过为了能够让自家的手机拥有更多的标志性特色,大部分的手...

weixin_35547906的博客 280

android手机进入fastboot,安卓手机怎么进去fastboot模式?安卓手机进入fastboot模式的方法_系统圣地...

安卓手机怎么进入Fastboot模式呢?有些小伙伴还不太清楚怎么进入Fastboot模式,还有些小伙伴连Fastboot模式是做什么的都还不太了解,今天小编就给大家带来有关安卓手机Fastboot模式的相关教程,希望能对大家有所帮助。从字面意思来讲,Fastboot是一个英文单词,翻译成中文的意思是『快速启动』。通常大家所讨论的Fastboot,通常都是说安卓手机的Fastboot模式。在安卓手机...

weixin_42503223的博客 2295

安卓手机Charles证书安装位置查询与安装2

安卓手机Charles证书安装位置查询与安装

晓飛的博客 5475
上一篇: Android驱动开发前的准备
下一篇: 操作系统的运行机制
onnx
博客等级 码龄5年 1万+粉丝 416原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

onnx

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值