117a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta/* 217a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta * Copyright (C) 2014 The Android Open Source Project 317a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta * 417a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta * Licensed under the Apache License, Version 2.0 (the "License"); 517a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta * you may not use this file except in compliance with the License. 617a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta * You may obtain a copy of the License at 717a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta * 817a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta * http://www.apache.org/licenses/LICENSE-2.0 917a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta * 1017a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta * Unless required by applicable law or agreed to in writing, software 1117a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta * distributed under the License is distributed on an "AS IS" BASIS, 1217a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1317a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta * See the License for the specific language governing permissions and 1417a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta * limitations under the License. 1517a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta */ 1617a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta 1717a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Guptapackage libcore.io; 1817a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta 1917a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Guptaimport com.android.layoutlib.bridge.impl.DelegateManager; 2017a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Guptaimport com.android.layoutlib.bridge.libcore.io.BridgeBufferIterator; 2117a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Guptaimport com.android.tools.layoutlib.annotations.LayoutlibDelegate; 2217a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta 2317a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Guptaimport android.system.ErrnoException; 2417a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta 2517a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Guptaimport java.io.File; 2617a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Guptaimport java.io.IOException; 2717a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Guptaimport java.io.RandomAccessFile; 285ceb7f6431f447aa9d4e949578ce5d4b90b8297cDeepanshu Guptaimport java.nio.ByteOrder; 2917a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Guptaimport java.nio.MappedByteBuffer; 3017a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Guptaimport java.nio.channels.FileChannel.MapMode; 3117a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Guptaimport java.util.HashMap; 3217a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Guptaimport java.util.Map; 3317a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta 3417a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta/** 3517a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta * Delegate used to provide alternate implementation of select methods of {@link MemoryMappedFile}. 3617a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta */ 3717a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Guptapublic class MemoryMappedFile_Delegate { 3817a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta 3917a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta private static final DelegateManager<MemoryMappedFile_Delegate> sManager = new 4017a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta DelegateManager<MemoryMappedFile_Delegate>(MemoryMappedFile_Delegate.class); 4117a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta 4217a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta private static final Map<MemoryMappedFile, Long> sMemoryMappedFileMap = 4317a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta new HashMap<MemoryMappedFile, Long>(); 4417a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta 4517a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta private final MappedByteBuffer mMappedByteBuffer; 4617a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta private final long mSize; 4717a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta 4817a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta /** Path on the target device where the data file is available. */ 4917a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta private static final String TARGET_PATH = System.getenv("ANDROID_ROOT") + "/usr/share/zoneinfo"; 5017a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta /** Path on the host (inside the SDK) where the data files are available. */ 5117a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta private static File sRootPath; 5217a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta 5317a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta @LayoutlibDelegate 5417a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta static MemoryMappedFile mmapRO(String path) throws ErrnoException { 5517a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta if (!path.startsWith(TARGET_PATH)) { 5617a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta throw new ErrnoException("Custom timezone data files are not supported.", 1); 5717a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta } 5817a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta if (sRootPath == null) { 5917a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta throw new ErrnoException("Bridge has not been initialized properly.", 1); 6017a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta } 6117a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta path = path.substring(TARGET_PATH.length()); 6217a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta try { 635ceb7f6431f447aa9d4e949578ce5d4b90b8297cDeepanshu Gupta File f = new File(sRootPath, path); 645ceb7f6431f447aa9d4e949578ce5d4b90b8297cDeepanshu Gupta if (!f.exists()) { 655ceb7f6431f447aa9d4e949578ce5d4b90b8297cDeepanshu Gupta throw new ErrnoException("File not found: " + f.getPath(), 1); 665ceb7f6431f447aa9d4e949578ce5d4b90b8297cDeepanshu Gupta } 675ceb7f6431f447aa9d4e949578ce5d4b90b8297cDeepanshu Gupta RandomAccessFile file = new RandomAccessFile(f, "r"); 685ceb7f6431f447aa9d4e949578ce5d4b90b8297cDeepanshu Gupta try { 695ceb7f6431f447aa9d4e949578ce5d4b90b8297cDeepanshu Gupta long size = file.length(); 705ceb7f6431f447aa9d4e949578ce5d4b90b8297cDeepanshu Gupta MemoryMappedFile_Delegate newDelegate = new MemoryMappedFile_Delegate(file); 715ceb7f6431f447aa9d4e949578ce5d4b90b8297cDeepanshu Gupta long filePointer = file.getFilePointer(); 725ceb7f6431f447aa9d4e949578ce5d4b90b8297cDeepanshu Gupta MemoryMappedFile mmFile = new MemoryMappedFile(filePointer, size); 735ceb7f6431f447aa9d4e949578ce5d4b90b8297cDeepanshu Gupta long delegateIndex = sManager.addNewDelegate(newDelegate); 745ceb7f6431f447aa9d4e949578ce5d4b90b8297cDeepanshu Gupta sMemoryMappedFileMap.put(mmFile, delegateIndex); 755ceb7f6431f447aa9d4e949578ce5d4b90b8297cDeepanshu Gupta return mmFile; 765ceb7f6431f447aa9d4e949578ce5d4b90b8297cDeepanshu Gupta } finally { 775ceb7f6431f447aa9d4e949578ce5d4b90b8297cDeepanshu Gupta file.close(); 785ceb7f6431f447aa9d4e949578ce5d4b90b8297cDeepanshu Gupta } 7917a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta } catch (IOException e) { 8017a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta throw new ErrnoException("mmapRO", 1, e); 8117a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta } 8217a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta } 8317a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta 8417a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta @LayoutlibDelegate 8517a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta static void close(MemoryMappedFile thisFile) throws ErrnoException { 8617a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta Long index = sMemoryMappedFileMap.get(thisFile); 8717a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta if (index != null) { 8817a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta sMemoryMappedFileMap.remove(thisFile); 8917a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta sManager.removeJavaReferenceFor(index); 9017a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta } 9117a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta } 9217a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta 9317a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta @LayoutlibDelegate 9417a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta static BufferIterator bigEndianIterator(MemoryMappedFile file) { 9517a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta MemoryMappedFile_Delegate delegate = getDelegate(file); 965ceb7f6431f447aa9d4e949578ce5d4b90b8297cDeepanshu Gupta return new BridgeBufferIterator(delegate.mSize, delegate.mMappedByteBuffer.duplicate()); 9717a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta } 9817a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta 9917a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta // TODO: implement littleEndianIterator() 10017a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta 10117a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta public MemoryMappedFile_Delegate(RandomAccessFile file) throws IOException { 10217a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta mSize = file.length(); 10317a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta // It's weird that map() takes size as long, but returns MappedByteBuffer which uses an int 10417a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta // to store the marker to the position. 10517a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta mMappedByteBuffer = file.getChannel().map(MapMode.READ_ONLY, 0, mSize); 1065ceb7f6431f447aa9d4e949578ce5d4b90b8297cDeepanshu Gupta assert mMappedByteBuffer.order() == ByteOrder.BIG_ENDIAN; 10717a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta } 10817a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta 10917a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta public static void setDataDir(File path) { 11017a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta sRootPath = path; 11117a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta } 11217a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta 11317a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta private static MemoryMappedFile_Delegate getDelegate(MemoryMappedFile file) { 11417a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta Long index = sMemoryMappedFileMap.get(file); 11517a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta return index == null ? null : sManager.getDelegate(index); 11617a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta } 11717a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta 11817a6170c62e6f74f2881623a9c16f0b6fea54721Deepanshu Gupta} 119