19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License. 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 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 Projectpackage android.os; 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 19dea6a027610951541981467276d8cd8ba8abc28bJohn Reckimport android.system.ErrnoException; 209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 21761e0918d30b6a3f292625b44b86dffd1538bc78Bjorn Bringertimport java.io.FileDescriptor; 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.IOException; 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.InputStream; 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.OutputStream; 25dea6a027610951541981467276d8cd8ba8abc28bJohn Reckimport java.nio.ByteBuffer; 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 29dea6a027610951541981467276d8cd8ba8abc28bJohn Reck * MemoryFile is a wrapper for {@link SharedMemory} which can optionally be set to purgeable. 30dea6a027610951541981467276d8cd8ba8abc28bJohn Reck * 31dea6a027610951541981467276d8cd8ba8abc28bJohn Reck * Applications should generally prefer to use {@link SharedMemory} which offers more flexible 32dea6a027610951541981467276d8cd8ba8abc28bJohn Reck * access & control over the shared memory region than MemoryFile does. 33dea6a027610951541981467276d8cd8ba8abc28bJohn Reck * 34112d339673c379b71a989bd33b73648aafe58ce1Jesse Wilson * Purgeable files may have their contents reclaimed by the kernel 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * in low memory conditions (only if allowPurging is set to true). 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * After a file is purged, attempts to read or write the file will 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * cause an IOException to be thrown. 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 39dea6a027610951541981467276d8cd8ba8abc28bJohn Reckpublic class MemoryFile { 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static String TAG = "MemoryFile"; 41761e0918d30b6a3f292625b44b86dffd1538bc78Bjorn Bringert 42dea6a027610951541981467276d8cd8ba8abc28bJohn Reck // Returns 'true' if purged, 'false' otherwise 43dea6a027610951541981467276d8cd8ba8abc28bJohn Reck private static native boolean native_pin(FileDescriptor fd, boolean pin) throws IOException; 447bcbd511731e13b9f2778e6aa6c633417d266f5eMarco Nelissen private static native int native_get_size(FileDescriptor fd) throws IOException; 459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 46dea6a027610951541981467276d8cd8ba8abc28bJohn Reck private SharedMemory mSharedMemory; 47dea6a027610951541981467276d8cd8ba8abc28bJohn Reck private ByteBuffer mMapping; 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean mAllowPurging = false; // true if our ashmem region is unpinned 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 51963cd006c45716b034f656bf7e7179e6476f7e4dBjorn Bringert * Allocates a new ashmem region. The region is initially not purgable. 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param name optional name for the file (can be null). 54dea6a027610951541981467276d8cd8ba8abc28bJohn Reck * @param length of the memory file in bytes, must be positive. 559fc2e9c965c68d56a0caf812f7f6d38d15317063Bjorn Bringert * @throws IOException if the memory file could not be created. 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 579fc2e9c965c68d56a0caf812f7f6d38d15317063Bjorn Bringert public MemoryFile(String name, int length) throws IOException { 58dea6a027610951541981467276d8cd8ba8abc28bJohn Reck try { 59dea6a027610951541981467276d8cd8ba8abc28bJohn Reck mSharedMemory = SharedMemory.create(name, length); 60707108b4ef55c674a0235bf3b37c8395a27c839fJohn Reck mMapping = mSharedMemory.mapReadWrite(); 61dea6a027610951541981467276d8cd8ba8abc28bJohn Reck } catch (ErrnoException ex) { 62dea6a027610951541981467276d8cd8ba8abc28bJohn Reck ex.rethrowAsIOException(); 63963cd006c45716b034f656bf7e7179e6476f7e4dBjorn Bringert } 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 67963cd006c45716b034f656bf7e7179e6476f7e4dBjorn Bringert * Closes the memory file. If there are no other open references to the memory 68963cd006c45716b034f656bf7e7179e6476f7e4dBjorn Bringert * file, it will be deleted. 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void close() { 71761e0918d30b6a3f292625b44b86dffd1538bc78Bjorn Bringert deactivate(); 72dea6a027610951541981467276d8cd8ba8abc28bJohn Reck mSharedMemory.close(); 739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 75963cd006c45716b034f656bf7e7179e6476f7e4dBjorn Bringert /** 76963cd006c45716b034f656bf7e7179e6476f7e4dBjorn Bringert * Unmaps the memory file from the process's memory space, but does not close it. 77963cd006c45716b034f656bf7e7179e6476f7e4dBjorn Bringert * After this method has been called, read and write operations through this object 78963cd006c45716b034f656bf7e7179e6476f7e4dBjorn Bringert * will fail, but {@link #getFileDescriptor()} will still return a valid file descriptor. 79963cd006c45716b034f656bf7e7179e6476f7e4dBjorn Bringert * 80963cd006c45716b034f656bf7e7179e6476f7e4dBjorn Bringert * @hide 81963cd006c45716b034f656bf7e7179e6476f7e4dBjorn Bringert */ 82a006b47298539d89dc7a06b54c070cb3e986352aBjorn Bringert void deactivate() { 83dea6a027610951541981467276d8cd8ba8abc28bJohn Reck if (mMapping != null) { 84dea6a027610951541981467276d8cd8ba8abc28bJohn Reck SharedMemory.unmap(mMapping); 85dea6a027610951541981467276d8cd8ba8abc28bJohn Reck mMapping = null; 86761e0918d30b6a3f292625b44b86dffd1538bc78Bjorn Bringert } 87761e0918d30b6a3f292625b44b86dffd1538bc78Bjorn Bringert } 88761e0918d30b6a3f292625b44b86dffd1538bc78Bjorn Bringert 89dea6a027610951541981467276d8cd8ba8abc28bJohn Reck private void checkActive() throws IOException { 90dea6a027610951541981467276d8cd8ba8abc28bJohn Reck if (mMapping == null) { 91dea6a027610951541981467276d8cd8ba8abc28bJohn Reck throw new IOException("MemoryFile has been deactivated"); 92dea6a027610951541981467276d8cd8ba8abc28bJohn Reck } 93761e0918d30b6a3f292625b44b86dffd1538bc78Bjorn Bringert } 94761e0918d30b6a3f292625b44b86dffd1538bc78Bjorn Bringert 95dea6a027610951541981467276d8cd8ba8abc28bJohn Reck private void beginAccess() throws IOException { 96dea6a027610951541981467276d8cd8ba8abc28bJohn Reck checkActive(); 97dea6a027610951541981467276d8cd8ba8abc28bJohn Reck if (mAllowPurging) { 98dea6a027610951541981467276d8cd8ba8abc28bJohn Reck if (native_pin(mSharedMemory.getFileDescriptor(), true)) { 99dea6a027610951541981467276d8cd8ba8abc28bJohn Reck throw new IOException("MemoryFile has been purged"); 100dea6a027610951541981467276d8cd8ba8abc28bJohn Reck } 101dea6a027610951541981467276d8cd8ba8abc28bJohn Reck } 102761e0918d30b6a3f292625b44b86dffd1538bc78Bjorn Bringert } 103761e0918d30b6a3f292625b44b86dffd1538bc78Bjorn Bringert 104dea6a027610951541981467276d8cd8ba8abc28bJohn Reck private void endAccess() throws IOException { 105dea6a027610951541981467276d8cd8ba8abc28bJohn Reck if (mAllowPurging) { 106dea6a027610951541981467276d8cd8ba8abc28bJohn Reck native_pin(mSharedMemory.getFileDescriptor(), false); 1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 109112d339673c379b71a989bd33b73648aafe58ce1Jesse Wilson 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns the length of the memory file. 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return file length. 1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int length() { 116dea6a027610951541981467276d8cd8ba8abc28bJohn Reck return mSharedMemory.getSize(); 1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Is memory file purging enabled? 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return true if the file may be purged. 123dea6a027610951541981467276d8cd8ba8abc28bJohn Reck * 124dea6a027610951541981467276d8cd8ba8abc28bJohn Reck * @deprecated Purgable is considered generally fragile and hard to use safely. Applications 125dea6a027610951541981467276d8cd8ba8abc28bJohn Reck * are recommend to instead use {@link android.content.ComponentCallbacks2#onTrimMemory(int)} 126dea6a027610951541981467276d8cd8ba8abc28bJohn Reck * to react to memory events and release shared memory regions as appropriate. 1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 128dea6a027610951541981467276d8cd8ba8abc28bJohn Reck @Deprecated 1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean isPurgingAllowed() { 1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mAllowPurging; 1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Enables or disables purging of the memory file. 1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param allowPurging true if the operating system can purge the contents 1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * of the file in low memory situations 1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return previous value of allowPurging 139dea6a027610951541981467276d8cd8ba8abc28bJohn Reck * 140dea6a027610951541981467276d8cd8ba8abc28bJohn Reck * @deprecated Purgable is considered generally fragile and hard to use safely. Applications 141dea6a027610951541981467276d8cd8ba8abc28bJohn Reck * are recommend to instead use {@link android.content.ComponentCallbacks2#onTrimMemory(int)} 142dea6a027610951541981467276d8cd8ba8abc28bJohn Reck * to react to memory events and release shared memory regions as appropriate. 1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 144dea6a027610951541981467276d8cd8ba8abc28bJohn Reck @Deprecated 1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized public boolean allowPurging(boolean allowPurging) throws IOException { 1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean oldValue = mAllowPurging; 1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (oldValue != allowPurging) { 148dea6a027610951541981467276d8cd8ba8abc28bJohn Reck native_pin(mSharedMemory.getFileDescriptor(), !allowPurging); 1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mAllowPurging = allowPurging; 1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return oldValue; 1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Creates a new InputStream for reading from the memory file. 1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @return InputStream 1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public InputStream getInputStream() { 1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return new MemoryInputStream(); 1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Creates a new OutputStream for writing to the memory file. 1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @return OutputStream 1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public OutputStream getOutputStream() { 1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return new MemoryOutputStream(); 1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Reads bytes from the memory file. 1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Will throw an IOException if the file has been purged. 1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param buffer byte array to read bytes into. 1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param srcOffset offset into the memory file to read from. 1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param destOffset offset into the byte array buffer to read into. 1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param count number of bytes to read. 1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return number of bytes read. 181761e0918d30b6a3f292625b44b86dffd1538bc78Bjorn Bringert * @throws IOException if the memory file has been purged or deactivated. 1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 183112d339673c379b71a989bd33b73648aafe58ce1Jesse Wilson public int readBytes(byte[] buffer, int srcOffset, int destOffset, int count) 1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throws IOException { 185dea6a027610951541981467276d8cd8ba8abc28bJohn Reck beginAccess(); 186dea6a027610951541981467276d8cd8ba8abc28bJohn Reck try { 187dea6a027610951541981467276d8cd8ba8abc28bJohn Reck mMapping.position(srcOffset); 188dea6a027610951541981467276d8cd8ba8abc28bJohn Reck mMapping.get(buffer, destOffset, count); 189dea6a027610951541981467276d8cd8ba8abc28bJohn Reck } finally { 190dea6a027610951541981467276d8cd8ba8abc28bJohn Reck endAccess(); 191761e0918d30b6a3f292625b44b86dffd1538bc78Bjorn Bringert } 192dea6a027610951541981467276d8cd8ba8abc28bJohn Reck return count; 1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Write bytes to the memory file. 1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Will throw an IOException if the file has been purged. 1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param buffer byte array to write bytes from. 2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param srcOffset offset into the byte array buffer to write from. 2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param destOffset offset into the memory file to write to. 2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param count number of bytes to write. 203761e0918d30b6a3f292625b44b86dffd1538bc78Bjorn Bringert * @throws IOException if the memory file has been purged or deactivated. 2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void writeBytes(byte[] buffer, int srcOffset, int destOffset, int count) 2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throws IOException { 207dea6a027610951541981467276d8cd8ba8abc28bJohn Reck beginAccess(); 208dea6a027610951541981467276d8cd8ba8abc28bJohn Reck try { 209dea6a027610951541981467276d8cd8ba8abc28bJohn Reck mMapping.position(destOffset); 210dea6a027610951541981467276d8cd8ba8abc28bJohn Reck mMapping.put(buffer, srcOffset, count); 211dea6a027610951541981467276d8cd8ba8abc28bJohn Reck } finally { 212dea6a027610951541981467276d8cd8ba8abc28bJohn Reck endAccess(); 2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 216963cd006c45716b034f656bf7e7179e6476f7e4dBjorn Bringert /** 217a006b47298539d89dc7a06b54c070cb3e986352aBjorn Bringert * Gets a FileDescriptor for the memory file. 218963cd006c45716b034f656bf7e7179e6476f7e4dBjorn Bringert * 219963cd006c45716b034f656bf7e7179e6476f7e4dBjorn Bringert * The returned file descriptor is not duplicated. 220963cd006c45716b034f656bf7e7179e6476f7e4dBjorn Bringert * 221963cd006c45716b034f656bf7e7179e6476f7e4dBjorn Bringert * @throws IOException If the memory file has been closed. 222e4f60cce8552a565efacf4907242574b9e00492dJohn Reck * 223e4f60cce8552a565efacf4907242574b9e00492dJohn Reck * @hide 224963cd006c45716b034f656bf7e7179e6476f7e4dBjorn Bringert */ 225963cd006c45716b034f656bf7e7179e6476f7e4dBjorn Bringert public FileDescriptor getFileDescriptor() throws IOException { 226dea6a027610951541981467276d8cd8ba8abc28bJohn Reck return mSharedMemory.getFileDescriptor(); 227963cd006c45716b034f656bf7e7179e6476f7e4dBjorn Bringert } 228963cd006c45716b034f656bf7e7179e6476f7e4dBjorn Bringert 229963cd006c45716b034f656bf7e7179e6476f7e4dBjorn Bringert /** 2307bcbd511731e13b9f2778e6aa6c633417d266f5eMarco Nelissen * Returns the size of the memory file that the file descriptor refers to, 2317bcbd511731e13b9f2778e6aa6c633417d266f5eMarco Nelissen * or -1 if the file descriptor does not refer to a memory file. 232ec100900e63a8374ac010e7131d9c7e54c5e6984Marco Nelissen * 233ec100900e63a8374ac010e7131d9c7e54c5e6984Marco Nelissen * @throws IOException If <code>fd</code> is not a valid file descriptor. 234ec100900e63a8374ac010e7131d9c7e54c5e6984Marco Nelissen * 235ec100900e63a8374ac010e7131d9c7e54c5e6984Marco Nelissen * @hide 236ec100900e63a8374ac010e7131d9c7e54c5e6984Marco Nelissen */ 2377bcbd511731e13b9f2778e6aa6c633417d266f5eMarco Nelissen public static int getSize(FileDescriptor fd) throws IOException { 2387bcbd511731e13b9f2778e6aa6c633417d266f5eMarco Nelissen return native_get_size(fd); 239963cd006c45716b034f656bf7e7179e6476f7e4dBjorn Bringert } 240963cd006c45716b034f656bf7e7179e6476f7e4dBjorn Bringert 2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private class MemoryInputStream extends InputStream { 2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mMark = 0; 2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mOffset = 0; 2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private byte[] mSingleByte; 2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int available() throws IOException { 249dea6a027610951541981467276d8cd8ba8abc28bJohn Reck if (mOffset >= mSharedMemory.getSize()) { 2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0; 2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 252dea6a027610951541981467276d8cd8ba8abc28bJohn Reck return mSharedMemory.getSize() - mOffset; 2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean markSupported() { 2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void mark(int readlimit) { 2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mMark = mOffset; 2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void reset() throws IOException { 2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mOffset = mMark; 2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int read() throws IOException { 2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mSingleByte == null) { 2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSingleByte = new byte[1]; 2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int result = read(mSingleByte, 0, 1); 2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (result != 1) { 277c1823701cc76790494fb622fe58f0942236cd7d0Bjorn Bringert return -1; 2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mSingleByte[0]; 2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int read(byte buffer[], int offset, int count) throws IOException { 284c1823701cc76790494fb622fe58f0942236cd7d0Bjorn Bringert if (offset < 0 || count < 0 || offset + count > buffer.length) { 285c1823701cc76790494fb622fe58f0942236cd7d0Bjorn Bringert // readBytes() also does this check, but we need to do it before 286c1823701cc76790494fb622fe58f0942236cd7d0Bjorn Bringert // changing count. 287c1823701cc76790494fb622fe58f0942236cd7d0Bjorn Bringert throw new IndexOutOfBoundsException(); 288c1823701cc76790494fb622fe58f0942236cd7d0Bjorn Bringert } 289c1823701cc76790494fb622fe58f0942236cd7d0Bjorn Bringert count = Math.min(count, available()); 290c1823701cc76790494fb622fe58f0942236cd7d0Bjorn Bringert if (count < 1) { 291c1823701cc76790494fb622fe58f0942236cd7d0Bjorn Bringert return -1; 292c1823701cc76790494fb622fe58f0942236cd7d0Bjorn Bringert } 2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int result = readBytes(buffer, mOffset, offset, count); 2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (result > 0) { 2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mOffset += result; 2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return result; 2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public long skip(long n) throws IOException { 302dea6a027610951541981467276d8cd8ba8abc28bJohn Reck if (mOffset + n > mSharedMemory.getSize()) { 303dea6a027610951541981467276d8cd8ba8abc28bJohn Reck n = mSharedMemory.getSize() - mOffset; 3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mOffset += n; 3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return n; 3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private class MemoryOutputStream extends OutputStream { 3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mOffset = 0; 3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private byte[] mSingleByte; 3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void write(byte buffer[], int offset, int count) throws IOException { 3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project writeBytes(buffer, offset, mOffset, count); 318112d339673c379b71a989bd33b73648aafe58ce1Jesse Wilson mOffset += count; 3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void write(int oneByte) throws IOException { 3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mSingleByte == null) { 3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSingleByte = new byte[1]; 3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSingleByte[0] = (byte)oneByte; 3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project write(mSingleByte, 0, 1); 3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 331