1 // Copyright 2014 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 package org.chromium.base; 6 7 import android.content.res.AssetFileDescriptor; 8 import android.content.res.AssetManager; 9 import android.util.Log; 10 11 import org.chromium.base.annotations.CalledByNative; 12 import org.chromium.base.annotations.JNINamespace; 13 14 import java.io.IOException; 15 16 /** 17 * A utility class to retrieve references to uncompressed assets insides the apk. A reference is 18 * defined as tuple (file descriptor, offset, size) enabling direct mapping without deflation. 19 * This can be used even within the renderer process, since it just dup's the apk's fd. 20 */ 21 @JNINamespace("base::android") 22 public class ApkAssets { 23 private static final String LOGTAG = "ApkAssets"; 24 25 @CalledByNative open(String fileName)26 public static long[] open(String fileName) { 27 AssetFileDescriptor afd = null; 28 try { 29 AssetManager manager = ContextUtils.getApplicationContext().getAssets(); 30 afd = manager.openNonAssetFd(fileName); 31 return new long[] {afd.getParcelFileDescriptor().detachFd(), afd.getStartOffset(), 32 afd.getLength()}; 33 } catch (IOException e) { 34 // As a general rule there's no point logging here because the caller should handle 35 // receiving an fd of -1 sensibly, and the log message is either mirrored later, or 36 // unwanted (in the case where a missing file is expected), or wanted but will be 37 // ignored, as most non-fatal logs are. 38 // It makes sense to log here when the file exists, but is unable to be opened as an fd 39 // because (for example) it is unexpectedly compressed in an apk. In that case, the log 40 // message might save someone some time working out what has gone wrong. 41 // For that reason, we only suppress the message when the exception message doesn't look 42 // informative (Android framework passes the filename as the message on actual file not 43 // found, and the empty string also wouldn't give any useful information for debugging). 44 if (!e.getMessage().equals("") && !e.getMessage().equals(fileName)) { 45 Log.e(LOGTAG, "Error while loading asset " + fileName + ": " + e); 46 } 47 return new long[] {-1, -1, -1}; 48 } finally { 49 try { 50 if (afd != null) { 51 afd.close(); 52 } 53 } catch (IOException e2) { 54 Log.e(LOGTAG, "Unable to close AssetFileDescriptor", e2); 55 } 56 } 57 } 58 } 59