db360642ed
Use Vendor ID, Product ID and optionally the Version to locate keymaps and configuration files for external devices. Moved virtual key definition parsing to native code so that EventHub can identify touch screens with virtual keys and load the appropriate key layout file. Cleaned up a lot of old code in EventHub. Fixed a regression in ViewRoot's fallback event handling. Fixed a minor bug in FileMap that caused it to try to munmap or close invalid handled when released if the attempt to map the file failed. Added a couple of new String8 conveniences for formatting strings. Modified Tokenizer to fall back to open+read when mmap fails since we can't mmap sysfs files as needed to open the virtual key definition files in /sys/board_properties/. Change-Id: I6ca5e5f9547619fd082ddac47e87ce185da69ee6
225 lines
5.7 KiB
C++
225 lines
5.7 KiB
C++
/*
|
|
* Copyright (C) 2006 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
//
|
|
// Shared file mapping class.
|
|
//
|
|
|
|
#define LOG_TAG "filemap"
|
|
|
|
#include <utils/FileMap.h>
|
|
#include <utils/Log.h>
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
|
|
#ifdef HAVE_POSIX_FILEMAP
|
|
#include <sys/mman.h>
|
|
#endif
|
|
|
|
#include <string.h>
|
|
#include <memory.h>
|
|
#include <errno.h>
|
|
#include <assert.h>
|
|
|
|
using namespace android;
|
|
|
|
/*static*/ long FileMap::mPageSize = -1;
|
|
|
|
|
|
/*
|
|
* Constructor. Create an empty object.
|
|
*/
|
|
FileMap::FileMap(void)
|
|
: mRefCount(1), mFileName(NULL), mBasePtr(NULL), mBaseLength(0),
|
|
mDataPtr(NULL), mDataLength(0)
|
|
{
|
|
}
|
|
|
|
/*
|
|
* Destructor.
|
|
*/
|
|
FileMap::~FileMap(void)
|
|
{
|
|
assert(mRefCount == 0);
|
|
|
|
//printf("+++ removing FileMap %p %u\n", mDataPtr, mDataLength);
|
|
|
|
mRefCount = -100; // help catch double-free
|
|
if (mFileName != NULL) {
|
|
free(mFileName);
|
|
}
|
|
#ifdef HAVE_POSIX_FILEMAP
|
|
if (mBasePtr && munmap(mBasePtr, mBaseLength) != 0) {
|
|
LOGD("munmap(%p, %d) failed\n", mBasePtr, (int) mBaseLength);
|
|
}
|
|
#endif
|
|
#ifdef HAVE_WIN32_FILEMAP
|
|
if (mBasePtr && UnmapViewOfFile(mBasePtr) == 0) {
|
|
LOGD("UnmapViewOfFile(%p) failed, error = %ld\n", mBasePtr,
|
|
GetLastError() );
|
|
}
|
|
if (mFileMapping != INVALID_HANDLE_VALUE) {
|
|
CloseHandle(mFileMapping);
|
|
}
|
|
CloseHandle(mFileHandle);
|
|
#endif
|
|
}
|
|
|
|
|
|
/*
|
|
* Create a new mapping on an open file.
|
|
*
|
|
* Closing the file descriptor does not unmap the pages, so we don't
|
|
* claim ownership of the fd.
|
|
*
|
|
* Returns "false" on failure.
|
|
*/
|
|
bool FileMap::create(const char* origFileName, int fd, off_t offset, size_t length, bool readOnly)
|
|
{
|
|
#ifdef HAVE_WIN32_FILEMAP
|
|
int adjust;
|
|
off_t adjOffset;
|
|
size_t adjLength;
|
|
|
|
if (mPageSize == -1) {
|
|
SYSTEM_INFO si;
|
|
|
|
GetSystemInfo( &si );
|
|
mPageSize = si.dwAllocationGranularity;
|
|
}
|
|
|
|
DWORD protect = readOnly ? PAGE_READONLY : PAGE_READWRITE;
|
|
|
|
mFileHandle = (HANDLE) _get_osfhandle(fd);
|
|
mFileMapping = CreateFileMapping( mFileHandle, NULL, protect, 0, 0, NULL);
|
|
if (mFileMapping == NULL) {
|
|
LOGE("CreateFileMapping(%p, %lx) failed with error %ld\n",
|
|
mFileHandle, protect, GetLastError() );
|
|
return false;
|
|
}
|
|
|
|
adjust = offset % mPageSize;
|
|
adjOffset = offset - adjust;
|
|
adjLength = length + adjust;
|
|
|
|
mBasePtr = MapViewOfFile( mFileMapping,
|
|
readOnly ? FILE_MAP_READ : FILE_MAP_ALL_ACCESS,
|
|
0,
|
|
(DWORD)(adjOffset),
|
|
adjLength );
|
|
if (mBasePtr == NULL) {
|
|
LOGE("MapViewOfFile(%ld, %ld) failed with error %ld\n",
|
|
adjOffset, adjLength, GetLastError() );
|
|
CloseHandle(mFileMapping);
|
|
mFileMapping = INVALID_HANDLE_VALUE;
|
|
return false;
|
|
}
|
|
#endif
|
|
#ifdef HAVE_POSIX_FILEMAP
|
|
int prot, flags, adjust;
|
|
off_t adjOffset;
|
|
size_t adjLength;
|
|
|
|
void* ptr;
|
|
|
|
assert(mRefCount == 1);
|
|
assert(fd >= 0);
|
|
assert(offset >= 0);
|
|
assert(length > 0);
|
|
|
|
/* init on first use */
|
|
if (mPageSize == -1) {
|
|
#if NOT_USING_KLIBC
|
|
mPageSize = sysconf(_SC_PAGESIZE);
|
|
if (mPageSize == -1) {
|
|
LOGE("could not get _SC_PAGESIZE\n");
|
|
return false;
|
|
}
|
|
#else
|
|
/* this holds for Linux, Darwin, Cygwin, and doesn't pain the ARM */
|
|
mPageSize = 4096;
|
|
#endif
|
|
}
|
|
|
|
adjust = offset % mPageSize;
|
|
try_again:
|
|
adjOffset = offset - adjust;
|
|
adjLength = length + adjust;
|
|
|
|
flags = MAP_SHARED;
|
|
prot = PROT_READ;
|
|
if (!readOnly)
|
|
prot |= PROT_WRITE;
|
|
|
|
ptr = mmap(NULL, adjLength, prot, flags, fd, adjOffset);
|
|
if (ptr == MAP_FAILED) {
|
|
// Cygwin does not seem to like file mapping files from an offset.
|
|
// So if we fail, try again with offset zero
|
|
if (adjOffset > 0) {
|
|
adjust = offset;
|
|
goto try_again;
|
|
}
|
|
|
|
LOGE("mmap(%ld,%ld) failed: %s\n",
|
|
(long) adjOffset, (long) adjLength, strerror(errno));
|
|
return false;
|
|
}
|
|
mBasePtr = ptr;
|
|
#endif /* HAVE_POSIX_FILEMAP */
|
|
|
|
mFileName = origFileName != NULL ? strdup(origFileName) : NULL;
|
|
mBaseLength = adjLength;
|
|
mDataOffset = offset;
|
|
mDataPtr = (char*) mBasePtr + adjust;
|
|
mDataLength = length;
|
|
|
|
assert(mBasePtr != NULL);
|
|
|
|
LOGV("MAP: base %p/%d data %p/%d\n",
|
|
mBasePtr, (int) mBaseLength, mDataPtr, (int) mDataLength);
|
|
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
* Provide guidance to the system.
|
|
*/
|
|
int FileMap::advise(MapAdvice advice)
|
|
{
|
|
#if HAVE_MADVISE
|
|
int cc, sysAdvice;
|
|
|
|
switch (advice) {
|
|
case NORMAL: sysAdvice = MADV_NORMAL; break;
|
|
case RANDOM: sysAdvice = MADV_RANDOM; break;
|
|
case SEQUENTIAL: sysAdvice = MADV_SEQUENTIAL; break;
|
|
case WILLNEED: sysAdvice = MADV_WILLNEED; break;
|
|
case DONTNEED: sysAdvice = MADV_DONTNEED; break;
|
|
default:
|
|
assert(false);
|
|
return -1;
|
|
}
|
|
|
|
cc = madvise(mBasePtr, mBaseLength, sysAdvice);
|
|
if (cc != 0)
|
|
LOGW("madvise(%d) failed: %s\n", sysAdvice, strerror(errno));
|
|
return cc;
|
|
#else
|
|
return -1;
|
|
#endif // HAVE_MADVISE
|
|
}
|