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