Home | History | Annotate | Download | only in base
      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