Android native CursorWindow数据保存原理

AgentScope实战训练营:构建计划可视化管理和HITL的AI智能计划助手 本文基于AgentScope Java SDK和Spring Boot WebFlux,从零构建一个支持SSE流式对话、计划可视化管理和HITL的AI智能计划助手Web应用PlanNotebook。涵盖项目架构设计、ReActAgent初始化、自定义工具注册、Hook机制实现、SSE事件协议定义、前端流式渲染等核心技术点,提供完整可运行的代码示例和详细的REST API参考。 阅读详情

我们通过Uri查询数据库所得到的数据集,保存在native层的CursorWindow中。CursorWindow的实质是共享内存的抽象,以实现跨进程数据共享。共享内存所采用的实现方式是文件映射。

在ContentProvider端透过SQLiteDatabase的封装查询到的数据集保存在CursorWindow所指向的共享内存中,然后通过Binder把这片共享内存传递到ContentResolver端,即查询端。这样客户就可以通过Cursor来访问这块共享内存中的数据集了。

那么CursorWindow是如何实现的呢?

1.通过Create静态函数来创建

status_t CursorWindow::create(const String8& name, size_t size, CursorWindow** outCursorWindow) {
    String8 ashmemName("CursorWindow: ");
    ashmemName.append(name);//文件名

    status_t result;
    int ashmemFd = ashmem_create_region(ashmemName.string(), size);
    if (ashmemFd < 0) {
        result = -errno;
    } else {
        result = ashmem_set_prot_region(ashmemFd, PROT_READ | PROT_WRITE);
        if (result >= 0) {
            void* data = ::mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, ashmemFd, 0);//文件映射
            if (data == MAP_FAILED) {
                result = -errno;
            } else {
                result = ashmem_set_prot_region(ashmemFd, PROT_READ);
                if (result >= 0) {
                    CursorWindow* window = new CursorWindow(name, ashmemFd,
                            data, size, false /*readOnly*/);
                    result = window->clear();
                    if (!result) {
                        LOG_WINDOW("Created new CursorWindow: freeOffset=%d, "
                                "numRows=%d, numColumns=%d, mSize=%d, mData=%p",
                                window->mHeader->freeOffset,
                                window->mHeader->numRows,
                                window->mHeader->numColumns,
                                window->mSize, window->mData);
                        *outCursorWindow = window;
                        return OK;
                    }
                    delete window;
                }
            }
            ::munmap(data, size);
        }
        ::close(ashmemFd);
    }
    *outCursorWindow = NULL;
    return result;
}

2.通过文件句柄来创建。这种case应该是在客户端的创建出一个CursorWindow所采用。

status_t CursorWindow::createFromParcel(Parcel* parcel, CursorWindow** outCursorWindow) {
    String8 name = parcel->readString8();

    status_t result;
    int ashmemFd = parcel->readFileDescriptor();
    if (ashmemFd == int(BAD_TYPE)) {
        result = BAD_TYPE;
    } else {
        ssize_t size = ashmem_get_size_region(ashmemFd);
        if (size < 0) {
            result = UNKNOWN_ERROR;
        } else {
            int dupAshmemFd = ::dup(ashmemFd);
            if (dupAshmemFd < 0) {
                result = -errno;
            } else {
                void* data = ::mmap(NULL, size, PROT_READ, MAP_SHARED, dupAshmemFd, 0);
                if (data == MAP_FAILED) {
                    result = -errno;
                } else {
                    CursorWindow* window = new CursorWindow(name, dupAshmemFd,
                            data, size, true /*readOnly*/);
                    LOG_WINDOW("Created CursorWindow from parcel: freeOffset=%d, "
                            "numRows=%d, numColumns=%d, mSize=%d, mData=%p",
                            window->mHeader->freeOffset,
                            window->mHeader->numRows,
                            window->mHeader->numColumns,
                            window->mSize, window->mData);
                    *outCursorWindow = window;
                    return OK;
                }
                ::close(dupAshmemFd);
            }
        }
    }
    *outCursorWindow = NULL;
    return result;
}

CursorWindow是如何保存查询到的数据集的呢?

原理图如下:

没一行所对应的数据采用FieldSlot数组来表示。图中黄色部分表示一行所对应的数据。如果列所对应的数据是long或者double,那么就直接保存在FieldSlot中,如果是Blob或者String,那么就在FieldSlot中保存数据的便宜量。

FiledSlot的定义如下:

    struct FieldSlot {
    private:
        int32_t type;//列所对应的数据的类型
        union {
            double d;
            int64_t l;
            struct {
                uint32_t offset;
                uint32_t size;
            } buffer;
        } data;//data的数据类型是union,当type所表示的是String或者Blob的时候,offset表示的就是保存真实数据的buffer的偏移量,size表示buffer的大小

        friend class CursorWindow;
    } __attribute((packed));



Android功耗系列专题分析之四:待机概率性功耗高的失效分析 本文分析了Android设备待机功耗异常高的问题。通过日志发现系统休眠失败,原因是PowerManagerService.Display唤醒锁未被释放。进一步排查发现,指纹解锁功能在灭屏时未正确释放屏幕锁定,导致DisplayReady状态异常。解决方案是将指纹功能的背光控制与DisplayReady状态控制分离,使用两个变量独立管理。经验表明,快速定位问题比解决问题更重要,修改原生流程时需谨慎评估风险。 阅读详情

相关推荐

不用公网IP,如何在内网高效搭建RustDesk远程控制服务器?基于Windows Server 2019的完整实践

本文详细介绍了在Windows Server 2019上部署RustDesk远程控制服务器的完整实践方案,无需公网IP即可实现内网高效远程控制。从环境准备、基础服务安装到网络与安全配置,提供了零成本的私有化部署指南,适用于企业、校园等内网环境。

weixin_28737073的博客 455

Android源码分析-CursorWindow

在使用sqlite查询时,CursorWindow有2MB的内存大小限制(Android 4.4-Android 12),如果超出该大小会导致出现异常,进而影响业务。 此时需要采用分页查询的方式来解决这种问题。 分页查询的步骤为: 1、确定dataCount:使用SELECT COUNT(*) FROM Table WHERE xxx 获取所要查询的记录总数; 2、确定最大单条记录maxRecord:使用SELECT *,length(column1)+length(column

怒放的生命的博客 2614

从零到一:高通Memory QMVS测试环境搭建的避坑指南

本文详细介绍了高通Memory QMVS测试环境搭建的全流程避坑指南,涵盖硬件选择、软件配置、QMVS核心组件安装及测试执行技巧。重点解析了adb工具配置、QPST日志抓取等关键步骤,帮助工程师高效搭建稳定测试环境,避免常见兼容性和稳定性问题。

weixin_29251567的博客 557

Android出现CursorWindow: Window is full: requested allocation 1354087 bytes, free space 141032 bytes,

在使用SQLiteDatabase插入一个比较大的数据时,抛出如下异常: W/CursorWindow: Window is full: requested allocation 1354087 bytes, free space 141032 bytes, window size 2097152 bytes如下图所示: 这是因为: Android SQLite在光标返回行的窗口是指定了一个最大

wei_zhi的博客 1万+

永磁同步电机定子槽型设计实战:从梨形槽到矩形槽的NVH优化之路

本文深入探讨了永磁同步电机定子槽型设计在NVH优化中的关键作用,对比了梨形槽与矩形槽的性能差异。通过Ansys Maxwell仿真和实际案例,揭示了矩形槽在提升槽满率、降低电磁噪声方面的优势,并总结了五大设计黄金法则,为电机设计工程师提供了实用指导。

weixin_28740299的博客 494

远心F-theta镜ZEMAX设计

根据给出的F-theta镜的设计指标,对F-theta镜进行了具体的光学设计。从对F-theta镜设计思想的介绍出发,对选取的初始结构进行了优化设计,优化完成后,对所设计的F-theta镜进行了像质评价,通过点列图、场曲与畸变图、相对照度、能量集中度对所设计的F-theta镜进行了分析,最终,对F-theta镜的设计效果进行了验证。

hitliuyi17的博客 9435

Android SQLite的 select 操作分析

就像 《Android SQLiteStatement 编译、执行 分析》 中所说的,SQLite中所有SQL语句都需要先编译为stmt,然后执行。 上述文章介绍了SQLiteStatement在android层面的编译执行。然而,类SQLiteStatement只能用以执行无返回值或者只有一行一列(1X1)的sql语句,例如INSERT ALERT 等,而像SELECT这种返回结果可能多行多列的则不适用。 android对select提供了专门的执行方法rawQuery(),对其也有特殊的SQLiteQu

E飞 1万+

文献综述三大痛点用AI轻松解决!借助Gemini 3 Pro搞定检索难、阅读慢、框架乱问题(附 AI 提示词)

4)“漏斗式”结构:先介绍宏观领域的研究现状,再缩小范围,聚焦于与你课题直接先关的子领域,深入探讨与你研究变量直接相关的文献, 指出前人没做过、没做全或结论有矛盾的地方,再顺势提出你的研究课题,这种结构逻辑最清晰,能直接引导读者发现你研究的必要性。想要有针对性的搜到相关文献,必须先把模糊的研究题目拆解成精准的检索语言,这个时候就需要建立一个关键词矩阵,如核心词、同义词、学术术语、上下位词,以及对应的英文表达。请围绕【我的研究主题/关键词】,检索近5年发表的高被引的中英文文献,优先选择顶刊综述/论文。

智能AI让学术科研更容易 277

Android四大组件Content Provider在应用程序之间共享数据的原理分析

Android应用程序之间不能直接访问对方的数据文件的障碍在于每一个应用程序都有自己的用户ID,而每一个应用程序所创建的文件的读写权限都是只赋予给自己所属的用户,因此,就限制了应用程序之间相互读写数据的操作。我们知道,Binder进程间通信机制可以突破了以应用程序为边界的权限控制来实现在不同应用程序之间传输数据,而Content Provider组件在不同应用程序之间共享数据正是基于Binder进程间通信机制来实现的。虽然Binder进程间通信机制突破了以应用程序为边界的权限控制,但是它是安全可控的,因为.

CallmeZhe的博客 1111

多准则决策方法体系(AHP、熵权法、随机森林、加权线性法、TOPSIS、模糊综合评价)

多准则决策方法体系的基础,是由三大赋权方法和三大评价框架构成的 “3+3” 核心模块。赋权方法聚焦于准则重要性的量化,评价框架则专注于多准则信息的综合集成,二者共同覆盖了从 “确定权重” 到 “输出结果” 的全流程决策需求。

```On Earth, Be Water, By Coding``` 522

大模型系列——Ollama简明教程

在这篇文章中,我们将了解如何使用 Ollama、如何在 Ollama 中创建自己的模型 以及如何使用 Ollama 构建聊天机器人。这是深入研究 Ollama 的第一部分,以及我所学到的有关本地 LLM 的知识以及如何将它们用于基于推理的应用程序。在这篇文章中,你将了解——

2401_84052244的博客 1万+

Android实战技术:Cursor相关的性能问题

当数据库中存有大量数据的时候,用Cursor查询时要注意,有可能引发性能问题。数据库查询出来的Cursor都会由一个CursorWindow来进行数据管理,包括内存空间的申请和数据的填充。CursorWindow对Cursor中的内容大小有限制,限制为1024*1024也就是1M,换句话说Cursor中数据的大小不能超过1M,如果超过1M会引发如下的错误: 08-23 05:48:31.838:

稀有猿诉 7419

人工蜂群优化算法(ABC)详解:原理、实现与应用

人工蜂群算法(Artificial Bee Colony, ABC)是Karaboga于2005年提出的一种群体智能优化算法,其灵感来源于蜜蜂群体在自然界中高效的采蜜行为。该算法通过模拟雇佣蜂、观察蜂和侦察蜂三种角色的分工协作来寻找最优解。在ABC算法中,每个潜在的解决方案被视为一个“食物源”,其质量由适应度函数评估。雇佣蜂负责在已知优质食物源附近进行局部开采;观察蜂根据雇佣蜂分享的信息,以一定概率选择并跟进优质食物源;侦察蜂则随机探索新区域,防止种群陷入局部最优。

qq_42212808的博客 393

Android Trace性能分析实战:从卡顿定位到架构优化

Android Trace是深度诊断App运行时性能问题的核心技术,基于ART虚拟机的采样与插桩机制,可精确捕获Java/Kotlin、Native及系统调用栈的毫秒级执行轨迹。其原理超越传统日志打点,通过时间轴+调用栈+线程状态三维建模,揭示主线程阻塞、渲染瓶颈、ANR诱因与高功耗根源。技术价值在于实现‘无埋点’‘非侵入式’的原子级可观测性,支撑滑动卡顿排查、inflate耗时归因、协程挂起定位等高频场景。本文聚焦Android Studio Profiler中Trace功能的工程化落地,覆盖采样/插桩/

weixin_34248705的博客 436

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

全新代码编辑器Cursorwindow版本0.1.11:高效编程的新选择

全新代码编辑器Cursorwindow版本0.1.11:高效编程的新选择 去发现同类优质开源项目:https://gitcode.com/ 在编程的世界里,一个优秀的代码编辑器对于提高工作效率至关重要。Cursorwindow版本0.1.11,一款全新的代码编辑器,正逐渐成为开发者的新宠。以下是对Cursorwindow版本0.1.11的核心功能和应用场景的详细介绍。 项目介绍 Cursorwin...

gitblog_06735的博客 928

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

android cursor 实例化,SQLite Android数据库游标窗口分配2048 kb失败

我有一个例程,每秒多次对SQLite数据库运行不同的查询.过了一会儿,我会得到错误“android.database.CursorWindowAllocationException: – 2048 kb的光标窗口分配失败.#Open Cursors =”出现在LogCat中.我有应用程序日志内存使用情况,实际上当使用率达到一定限度时,我收到此错误,暗示它用完了.我的直觉告诉我每次运行查询时数据库...

weixin_39854923的博客 385

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

全新代码编辑器 Cursor window版本0.1.11

全新代码编辑器 Cursor window版本0.1.11 去发现同类优质开源项目:https://gitcode.com/ 介绍 Cursor window版本0.1.11是一款全新的代码编辑器,旨在为开发者提供更高效、更便捷的编程体验。这款编辑器不仅具备丰富的功能,还拥有简洁的界面设计,让您的编码过程更加愉悦。 功能特点 智能代码提示:自动完成代码,减少输入错误,提高编码效率。 代码格式化:...

gitblog_06754的博客 597

一文帮你搞懂 Android 文件描述符

介绍文件描述符的概念以及工作原理,并通过源码了解 Android 中常见的 FD 泄漏。 一、什么是文件描述符? 文件描述符是在 Linux 文件系统的被使用,由于Android基 于Linux系统,所以Android也继承了文件描述符系统。我们都知道,在Linux中一切皆文件,所以系统在运行时有大量的文件操作,内核为了高效管理已被打开的文件会创建索引,用来指向被打开的文件,这个索引即是文件描述符,其表现形式为一个非负整数。 可以通过命令ls -la /proc/$pid/fd查看当前进程...

vivo互联网技术 2289

android 多界面光标,android.database.CursorWindowAllocationException:光标窗口分配2048 kb失败,即使关闭游标...

关于CursorWindowAllocatoinException有很多关于SO的问题:他们都建议游标在使用后必须关闭.但这并没有解决我的问题.这是我的代码:String query = "select serial from tbl1 union select serial from tbl2 union select serial from tbl3";sqliteDatabase db = ...

weixin_32629853的博客 962

[Android]CursorWindow何时创建

2019独角兽企业重金招聘Python工程师标准>>> ...

weixin_34168880的博客 255

处理华为Framework层中curosr和空指针问题(反编译ROM和Hook动态代理)

处理华为ROM 源码报错(cursor和空指针),通过反编译华为 framework.dex 进行源码分析,Hook 动态代理来解决。

HeXinGen的博客 1659

今天解决了cursor游标越界的问题

经过仔细分析了,最后发现,没有删除原来的数据库表导致的问题,更新的数据写不进去,把原来的表删除,或者,重新卸载应用,让它第一次加载数据,即可把新更新的数据添加到数据库中

路遥知马力 1616

【Android开发精要笔记】Android组件模型解析

Android组件模型解析 Android中的Mashup 将应用切分成不同类别的组件,通过统一的定位模型和接口标准将他们整合在一起,来共同完成某项任务。在Android的Mashup模式下,每个组件的功能都可以被充分的复用。来自不同应用的组件可以有机地结合在一起,共同完成任务。 基于Mashup的Android应用模型 三个基本要素:组件、连接、配置 接口就是实现单元。从代码来看,...

weixin_30698297的博客 227
上一篇: 跟着Android学设计模式:代理(proxy)
下一篇: JNI设计概述
Sailingthink
博客等级 码龄14年 31粉丝 26原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值