@FixWhenMinSdkVersion(9) // IOException(String, Throwable) will be available
  public static StatStruct getStat(String path) throws IOException {
    // IMPLEMENTATION NOTE: This method uses Reflection to invoke
    // android.os.FileUtils.getFileStatus(path) which returns FileStatus.
    // In JellyBean MR1 FileUtils.getFileStatus was removed. Thus, we fall back to
    // libcore.io.Libcore.os.stat(path).
    // Since Libcore is not available until ICS, we have to keep using FileUtils and falling back
    // to Libcore.

    // Try android.os.FileUtils.getFileStatus(path)
    try {
      @FixWhenMinSdkVersion(14) // Use Libcore unconditionally
      Object obj = Class.forName("android.os.FileUtils$FileStatus").newInstance();
      boolean success = (Boolean) Class.forName("android.os.FileUtils")
          .getMethod("getFileStatus", String.class,
              Class.forName("android.os.FileUtils$FileStatus"))
          .invoke(null, path, obj);
      if (success) {
        StatStruct stat = new StatStruct();
        stat.dev = getFileStatusInt(obj, "dev");
        stat.ino = getFileStatusInt(obj, "ino");
        stat.mode = getFileStatusInt(obj, "mode");
        stat.nlink = getFileStatusInt(obj, "nlink");
        stat.uid = getFileStatusInt(obj, "uid");
        stat.gid = getFileStatusInt(obj, "gid");
        stat.rdev = getFileStatusInt(obj, "rdev");
        stat.size = getFileStatusLong(obj, "size");
        stat.blksize = getFileStatusInt(obj, "blksize");
        stat.blocks = getFileStatusLong(obj, "blocks");
        stat.atime = getFileStatusLong(obj, "atime");
        stat.mtime = getFileStatusLong(obj, "mtime");
        stat.ctime = getFileStatusLong(obj, "ctime");
        return stat;
      } else {
        throw new IOException("FileUtils.getFileStatus returned with failure.");
      }
    } catch (ClassNotFoundException ignored) {
      // FileUtils.FileStatus not found. Fall back to Libcore.os.stat() and the resulting
      // libcore.io.StructStat
    } catch (Exception e) {
      // Can't chain exception because IOException doesn't have the right constructor on Froyo
      // and below
      throw new IOException("Failed to get FileStatus: " + e);
    }

    // Try libcore.io.Libcore.os.stat(path)
    try {
      // Get the Libcore.os static field
      Object os = Class.forName("libcore.io.Libcore").getField("os").get(null);
      // Invoke Libcore.os.stat(String)
      Object structStat = os.getClass().getMethod("stat", String.class).invoke(os, path);
      if (structStat != null) {
        StatStruct stat = new StatStruct();
        stat.dev = getLibcoreFileStatusLong(structStat, "st_dev");
        stat.ino = getLibcoreFileStatusLong(structStat, "st_ino");
        stat.mode = getLibcoreFileStatusInt(structStat, "st_mode");
        stat.nlink = getLibcoreFileStatusLong(structStat, "st_nlink");
        stat.uid = getLibcoreFileStatusInt(structStat, "st_uid");
        stat.gid = getLibcoreFileStatusInt(structStat, "st_gid");
        stat.rdev = getLibcoreFileStatusLong(structStat, "st_rdev");
        stat.size = getLibcoreFileStatusLong(structStat, "st_size");
        stat.blksize = getLibcoreFileStatusLong(structStat, "st_blksize");
        stat.blocks = getLibcoreFileStatusLong(structStat, "st_blocks");
        stat.atime = getLibcoreFileStatusLong(structStat, "st_atime");
        stat.mtime = getLibcoreFileStatusLong(structStat, "st_mtime");
        stat.ctime = getLibcoreFileStatusLong(structStat, "st_ctime");
        return stat;
      } else {
        throw new IOException("Libcore.os.stat returned null");
      }
    } catch (Exception e) {
      // Can't chain exception because IOException doesn't have the right constructor on Froyo
      // and below
      throw new IOException("Failed to get FileStatus: " + e);
    }
  }
Gets filesystem information about the provided path.
java/com/google/android/apps/authenticator/util/FileUtilities.java