19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2006-2007 The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
400adb8685ee996f9d2650d617c8c0e98f13ef406Mark Salyzyn * Licensed under the Apache License, Version 2.0 (the "License");
500adb8685ee996f9d2650d617c8c0e98f13ef406Mark Salyzyn * you may not use this file except in compliance with the License.
600adb8685ee996f9d2650d617c8c0e98f13ef406Mark Salyzyn * You may obtain a copy of the License at
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
800adb8685ee996f9d2650d617c8c0e98f13ef406Mark Salyzyn *      http://www.apache.org/licenses/LICENSE-2.0
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
1000adb8685ee996f9d2650d617c8c0e98f13ef406Mark Salyzyn * Unless required by applicable law or agreed to in writing, software
1100adb8685ee996f9d2650d617c8c0e98f13ef406Mark Salyzyn * distributed under the License is distributed on an "AS IS" BASIS,
1200adb8685ee996f9d2650d617c8c0e98f13ef406Mark Salyzyn * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1300adb8685ee996f9d2650d617c8c0e98f13ef406Mark Salyzyn * See the License for the specific language governing permissions and
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License.
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#undef LOG_TAG
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define LOG_TAG "CursorWindow"
199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2049d2b1864c3dfec6faff74d67cb2527a8f1af5a8Mathias Agopian#include <androidfw/CursorWindow.h>
219d3b1a424c5c61e24e9659d15fb353026a00d925Jeff Brown#include <binder/Parcel.h>
229d3b1a424c5c61e24e9659d15fb353026a00d925Jeff Brown#include <utils/Log.h>
230cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown
240cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown#include <cutils/ashmem.h>
250cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown#include <sys/mman.h>
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <assert.h>
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <string.h>
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <stdlib.h>
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectnamespace android {
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
330cde89f5f025b7826be009ebb9673b970e180e32Jeff BrownCursorWindow::CursorWindow(const String8& name, int ashmemFd,
340cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown        void* data, size_t size, bool readOnly) :
350cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown        mName(name), mAshmemFd(ashmemFd), mData(data), mSize(size), mReadOnly(readOnly) {
360cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    mHeader = static_cast<Header*>(mData);
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
390cde89f5f025b7826be009ebb9673b970e180e32Jeff BrownCursorWindow::~CursorWindow() {
400cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    ::munmap(mData, mSize);
410cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    ::close(mAshmemFd);
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
445e5d6d8ba04d7579df840cda055cd5dfa9d7666fJeff Brownstatus_t CursorWindow::create(const String8& name, size_t size, CursorWindow** outCursorWindow) {
450cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    String8 ashmemName("CursorWindow: ");
460cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    ashmemName.append(name);
470cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown
480cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    status_t result;
490cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    int ashmemFd = ashmem_create_region(ashmemName.string(), size);
500cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    if (ashmemFd < 0) {
510cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown        result = -errno;
520cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    } else {
530cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown        result = ashmem_set_prot_region(ashmemFd, PROT_READ | PROT_WRITE);
540cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown        if (result >= 0) {
550cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown            void* data = ::mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, ashmemFd, 0);
560cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown            if (data == MAP_FAILED) {
570cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown                result = -errno;
580cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown            } else {
590cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown                result = ashmem_set_prot_region(ashmemFd, PROT_READ);
600cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown                if (result >= 0) {
610cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown                    CursorWindow* window = new CursorWindow(name, ashmemFd,
620cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown                            data, size, false /*readOnly*/);
630cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown                    result = window->clear();
640cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown                    if (!result) {
650cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown                        LOG_WINDOW("Created new CursorWindow: freeOffset=%d, "
660cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown                                "numRows=%d, numColumns=%d, mSize=%d, mData=%p",
670cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown                                window->mHeader->freeOffset,
680cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown                                window->mHeader->numRows,
690cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown                                window->mHeader->numColumns,
700cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown                                window->mSize, window->mData);
710cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown                        *outCursorWindow = window;
720cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown                        return OK;
730cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown                    }
740cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown                    delete window;
750cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown                }
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
770cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown            ::munmap(data, size);
780cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown        }
790cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown        ::close(ashmemFd);
800cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    }
810cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    *outCursorWindow = NULL;
820cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    return result;
830cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown}
840cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown
850cde89f5f025b7826be009ebb9673b970e180e32Jeff Brownstatus_t CursorWindow::createFromParcel(Parcel* parcel, CursorWindow** outCursorWindow) {
860cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    String8 name = parcel->readString8();
870cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown
880cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    status_t result;
890cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    int ashmemFd = parcel->readFileDescriptor();
900cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    if (ashmemFd == int(BAD_TYPE)) {
910cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown        result = BAD_TYPE;
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } else {
930cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown        ssize_t size = ashmem_get_size_region(ashmemFd);
940cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown        if (size < 0) {
950cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown            result = UNKNOWN_ERROR;
960cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown        } else {
970cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown            int dupAshmemFd = ::dup(ashmemFd);
980cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown            if (dupAshmemFd < 0) {
990cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown                result = -errno;
1000cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown            } else {
10145e2e95c2ffeb2d978e2cce80b729ef6ada3b8d2Fyodor Kupolov                // the size of the ashmem descriptor can be modified between ashmem_get_size_region
10245e2e95c2ffeb2d978e2cce80b729ef6ada3b8d2Fyodor Kupolov                // call and mmap, so we'll check again immediately after memory is mapped
1030cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown                void* data = ::mmap(NULL, size, PROT_READ, MAP_SHARED, dupAshmemFd, 0);
1040cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown                if (data == MAP_FAILED) {
1050cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown                    result = -errno;
10645e2e95c2ffeb2d978e2cce80b729ef6ada3b8d2Fyodor Kupolov                } else if (ashmem_get_size_region(dupAshmemFd) != size) {
10745e2e95c2ffeb2d978e2cce80b729ef6ada3b8d2Fyodor Kupolov                    ::munmap(data, size);
10845e2e95c2ffeb2d978e2cce80b729ef6ada3b8d2Fyodor Kupolov                    result = BAD_VALUE;
1090cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown                } else {
1100cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown                    CursorWindow* window = new CursorWindow(name, dupAshmemFd,
1110cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown                            data, size, true /*readOnly*/);
1120cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown                    LOG_WINDOW("Created CursorWindow from parcel: freeOffset=%d, "
1130cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown                            "numRows=%d, numColumns=%d, mSize=%d, mData=%p",
1140cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown                            window->mHeader->freeOffset,
1150cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown                            window->mHeader->numRows,
1160cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown                            window->mHeader->numColumns,
1170cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown                            window->mSize, window->mData);
1180cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown                    *outCursorWindow = window;
1190cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown                    return OK;
1200cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown                }
1210cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown                ::close(dupAshmemFd);
1220cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown            }
1230cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown        }
1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1250cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    *outCursorWindow = NULL;
1260cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    return result;
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1290cde89f5f025b7826be009ebb9673b970e180e32Jeff Brownstatus_t CursorWindow::writeToParcel(Parcel* parcel) {
1300cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    status_t status = parcel->writeString8(mName);
1310cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    if (!status) {
1320cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown        status = parcel->writeDupFileDescriptor(mAshmemFd);
1330cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    }
1340cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    return status;
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1370cde89f5f025b7826be009ebb9673b970e180e32Jeff Brownstatus_t CursorWindow::clear() {
1380cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    if (mReadOnly) {
1390cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown        return INVALID_OPERATION;
1400cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    }
1410cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown
1420cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    mHeader->freeOffset = sizeof(Header) + sizeof(RowSlotChunk);
1430cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    mHeader->firstChunkOffset = sizeof(Header);
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mHeader->numRows = 0;
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mHeader->numColumns = 0;
1460cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown
1470cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    RowSlotChunk* firstChunk = static_cast<RowSlotChunk*>(offsetToPtr(mHeader->firstChunkOffset));
1480cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    firstChunk->nextChunkOffset = 0;
1490cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    return OK;
1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1520cde89f5f025b7826be009ebb9673b970e180e32Jeff Brownstatus_t CursorWindow::setNumColumns(uint32_t numColumns) {
1530cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    if (mReadOnly) {
1540cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown        return INVALID_OPERATION;
1550cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    }
1560cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown
1570cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    uint32_t cur = mHeader->numColumns;
1580cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    if ((cur > 0 || mHeader->numRows > 0) && cur != numColumns) {
1593762c311729fe9f3af085c14c5c1fb471d994c03Steve Block        ALOGE("Trying to go from %d columns to %d", cur, numColumns);
1600cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown        return INVALID_OPERATION;
1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1620cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    mHeader->numColumns = numColumns;
1630cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    return OK;
1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1660cde89f5f025b7826be009ebb9673b970e180e32Jeff Brownstatus_t CursorWindow::allocRow() {
1670cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    if (mReadOnly) {
1680cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown        return INVALID_OPERATION;
1690cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    }
1700cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown
1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Fill in the row slot
1720cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    RowSlot* rowSlot = allocRowSlot();
1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (rowSlot == NULL) {
1740cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown        return NO_MEMORY;
1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Allocate the slots for the field directory
1780cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    size_t fieldDirSize = mHeader->numColumns * sizeof(FieldSlot);
1790cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    uint32_t fieldDirOffset = alloc(fieldDirSize, true /*aligned*/);
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (!fieldDirOffset) {
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mHeader->numRows--;
1820cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown        LOG_WINDOW("The row failed, so back out the new row accounting "
1830cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown                "from allocRowSlot %d", mHeader->numRows);
1840cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown        return NO_MEMORY;
1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1860cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    FieldSlot* fieldDir = static_cast<FieldSlot*>(offsetToPtr(fieldDirOffset));
1870cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    memset(fieldDir, 0, fieldDirSize);
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1890cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    LOG_WINDOW("Allocated row %u, rowSlot is at offset %u, fieldDir is %d bytes at offset %u\n",
1900cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown            mHeader->numRows - 1, offsetFromPtr(rowSlot), fieldDirSize, fieldDirOffset);
1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    rowSlot->offset = fieldDirOffset;
1920cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    return OK;
1930cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown}
1940cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown
1950cde89f5f025b7826be009ebb9673b970e180e32Jeff Brownstatus_t CursorWindow::freeLastRow() {
1960cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    if (mReadOnly) {
1970cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown        return INVALID_OPERATION;
1980cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    }
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2000cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    if (mHeader->numRows > 0) {
2010cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown        mHeader->numRows--;
2020cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    }
2030cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    return OK;
2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2060cde89f5f025b7826be009ebb9673b970e180e32Jeff Brownuint32_t CursorWindow::alloc(size_t size, bool aligned) {
2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    uint32_t padding;
2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (aligned) {
2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // 4 byte alignment
2100cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown        padding = (~mHeader->freeOffset + 1) & 3;
2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } else {
2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        padding = 0;
2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2150cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    uint32_t offset = mHeader->freeOffset + padding;
2160cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    uint32_t nextFreeOffset = offset + size;
2170cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    if (nextFreeOffset > mSize) {
218f5df700e6ce056ebfa322314d970e52d6facc35aAshok Bhat        ALOGW("Window is full: requested allocation %zu bytes, "
219f5df700e6ce056ebfa322314d970e52d6facc35aAshok Bhat                "free space %zu bytes, window size %zu bytes",
2200cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown                size, freeSpace(), mSize);
2210cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown        return 0;
2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2240cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    mHeader->freeOffset = nextFreeOffset;
2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return offset;
2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2280cde89f5f025b7826be009ebb9673b970e180e32Jeff BrownCursorWindow::RowSlot* CursorWindow::getRowSlot(uint32_t row) {
2290cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    uint32_t chunkPos = row;
2300cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    RowSlotChunk* chunk = static_cast<RowSlotChunk*>(
2310cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown            offsetToPtr(mHeader->firstChunkOffset));
2320cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    while (chunkPos >= ROW_SLOT_CHUNK_NUM_ROWS) {
2330cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown        chunk = static_cast<RowSlotChunk*>(offsetToPtr(chunk->nextChunkOffset));
2340cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown        chunkPos -= ROW_SLOT_CHUNK_NUM_ROWS;
2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2360cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    return &chunk->slots[chunkPos];
2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2390cde89f5f025b7826be009ebb9673b970e180e32Jeff BrownCursorWindow::RowSlot* CursorWindow::allocRowSlot() {
2400cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    uint32_t chunkPos = mHeader->numRows;
2410cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    RowSlotChunk* chunk = static_cast<RowSlotChunk*>(
2420cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown            offsetToPtr(mHeader->firstChunkOffset));
2430cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    while (chunkPos > ROW_SLOT_CHUNK_NUM_ROWS) {
2440cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown        chunk = static_cast<RowSlotChunk*>(offsetToPtr(chunk->nextChunkOffset));
2450cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown        chunkPos -= ROW_SLOT_CHUNK_NUM_ROWS;
2460cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    }
2470cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    if (chunkPos == ROW_SLOT_CHUNK_NUM_ROWS) {
2480cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown        if (!chunk->nextChunkOffset) {
2490cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown            chunk->nextChunkOffset = alloc(sizeof(RowSlotChunk), true /*aligned*/);
2500cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown            if (!chunk->nextChunkOffset) {
2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return NULL;
2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2540cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown        chunk = static_cast<RowSlotChunk*>(offsetToPtr(chunk->nextChunkOffset));
2550cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown        chunk->nextChunkOffset = 0;
2560cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown        chunkPos = 0;
2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2580cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    mHeader->numRows += 1;
2590cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    return &chunk->slots[chunkPos];
2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2620cde89f5f025b7826be009ebb9673b970e180e32Jeff BrownCursorWindow::FieldSlot* CursorWindow::getFieldSlot(uint32_t row, uint32_t column) {
2630cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    if (row >= mHeader->numRows || column >= mHeader->numColumns) {
2643762c311729fe9f3af085c14c5c1fb471d994c03Steve Block        ALOGE("Failed to read row %d, column %d from a CursorWindow which "
2650cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown                "has %d rows, %d columns.",
2660cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown                row, column, mHeader->numRows, mHeader->numColumns);
2670cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown        return NULL;
2680cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    }
2690cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    RowSlot* rowSlot = getRowSlot(row);
2700cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    if (!rowSlot) {
2713762c311729fe9f3af085c14c5c1fb471d994c03Steve Block        ALOGE("Failed to find rowSlot for row %d.", row);
2720cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown        return NULL;
2730cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    }
2740cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    FieldSlot* fieldDir = static_cast<FieldSlot*>(offsetToPtr(rowSlot->offset));
2750cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    return &fieldDir[column];
2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2780cde89f5f025b7826be009ebb9673b970e180e32Jeff Brownstatus_t CursorWindow::putBlob(uint32_t row, uint32_t column, const void* value, size_t size) {
2790cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    return putBlobOrString(row, column, value, size, FIELD_TYPE_BLOB);
2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2820cde89f5f025b7826be009ebb9673b970e180e32Jeff Brownstatus_t CursorWindow::putString(uint32_t row, uint32_t column, const char* value,
2830cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown        size_t sizeIncludingNull) {
2840cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    return putBlobOrString(row, column, value, sizeIncludingNull, FIELD_TYPE_STRING);
2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2870cde89f5f025b7826be009ebb9673b970e180e32Jeff Brownstatus_t CursorWindow::putBlobOrString(uint32_t row, uint32_t column,
2880cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown        const void* value, size_t size, int32_t type) {
2890cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    if (mReadOnly) {
2900cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown        return INVALID_OPERATION;
2910cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    }
2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2930cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    FieldSlot* fieldSlot = getFieldSlot(row, column);
2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (!fieldSlot) {
2950cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown        return BAD_VALUE;
2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2980cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    uint32_t offset = alloc(size);
2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (!offset) {
3000cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown        return NO_MEMORY;
3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3030cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    memcpy(offsetToPtr(offset), value, size);
3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3050cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    fieldSlot->type = type;
3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    fieldSlot->data.buffer.offset = offset;
3070cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    fieldSlot->data.buffer.size = size;
3080cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    return OK;
3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3110cde89f5f025b7826be009ebb9673b970e180e32Jeff Brownstatus_t CursorWindow::putLong(uint32_t row, uint32_t column, int64_t value) {
3120cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    if (mReadOnly) {
3130cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown        return INVALID_OPERATION;
3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3160cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    FieldSlot* fieldSlot = getFieldSlot(row, column);
3170cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    if (!fieldSlot) {
3180cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown        return BAD_VALUE;
3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3210cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    fieldSlot->type = FIELD_TYPE_INTEGER;
3220cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    fieldSlot->data.l = value;
3230cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    return OK;
3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3260cde89f5f025b7826be009ebb9673b970e180e32Jeff Brownstatus_t CursorWindow::putDouble(uint32_t row, uint32_t column, double value) {
3270cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    if (mReadOnly) {
3280cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown        return INVALID_OPERATION;
3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3310cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    FieldSlot* fieldSlot = getFieldSlot(row, column);
3320cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    if (!fieldSlot) {
3330cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown        return BAD_VALUE;
3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3353bc6bbc92cd2095f42039b5aadd0a14d0e5d9230Jeff Brown
3360cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    fieldSlot->type = FIELD_TYPE_FLOAT;
3370cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    fieldSlot->data.d = value;
3380cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    return OK;
3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3410cde89f5f025b7826be009ebb9673b970e180e32Jeff Brownstatus_t CursorWindow::putNull(uint32_t row, uint32_t column) {
3420cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    if (mReadOnly) {
3430cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown        return INVALID_OPERATION;
3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3460cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    FieldSlot* fieldSlot = getFieldSlot(row, column);
3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (!fieldSlot) {
3480cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown        return BAD_VALUE;
3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3500cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown
3510cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    fieldSlot->type = FIELD_TYPE_NULL;
3520cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    fieldSlot->data.buffer.offset = 0;
3530cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    fieldSlot->data.buffer.size = 0;
3540cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown    return OK;
3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}; // namespace android
358