diff options
10 files changed, 244 insertions, 93 deletions
diff --git a/api/current.txt b/api/current.txt index dcc19e62d187..f4c6a8f29d23 100644 --- a/api/current.txt +++ b/api/current.txt @@ -9137,6 +9137,7 @@ package android.content { method public android.os.Bundle call(java.lang.String, java.lang.String, android.os.Bundle) throws android.os.RemoteException; method public final android.net.Uri canonicalize(android.net.Uri) throws android.os.RemoteException; method public void close(); + method public static void closeQuietly(android.content.ContentProviderClient); method public int delete(android.net.Uri, java.lang.String, java.lang.String[]) throws android.os.RemoteException; method public android.content.ContentProvider getLocalContentProvider(); method public java.lang.String[] getStreamTypes(android.net.Uri, java.lang.String) throws android.os.RemoteException; @@ -32547,6 +32548,21 @@ package android.os { ctor public FileUriExposedException(java.lang.String); } + public class FileUtils { + method public static void closeQuietly(java.lang.AutoCloseable); + method public static void closeQuietly(java.io.FileDescriptor); + method public static long copy(java.io.File, java.io.File) throws java.io.IOException; + method public static long copy(java.io.File, java.io.File, android.os.CancellationSignal, java.util.concurrent.Executor, android.os.FileUtils.ProgressListener) throws java.io.IOException; + method public static long copy(java.io.InputStream, java.io.OutputStream) throws java.io.IOException; + method public static long copy(java.io.InputStream, java.io.OutputStream, android.os.CancellationSignal, java.util.concurrent.Executor, android.os.FileUtils.ProgressListener) throws java.io.IOException; + method public static long copy(java.io.FileDescriptor, java.io.FileDescriptor) throws java.io.IOException; + method public static long copy(java.io.FileDescriptor, java.io.FileDescriptor, android.os.CancellationSignal, java.util.concurrent.Executor, android.os.FileUtils.ProgressListener) throws java.io.IOException; + } + + public static abstract interface FileUtils.ProgressListener { + method public abstract void onProgress(long); + } + public class Handler { ctor public Handler(); ctor public Handler(android.os.Handler.Callback); @@ -42510,13 +42526,11 @@ package android.telephony { method public java.lang.String getIccAuthentication(int, int, java.lang.String); method public java.lang.String getImei(); method public java.lang.String getImei(int); - method public java.lang.String getTypeAllocationCode(); - method public java.lang.String getTypeAllocationCode(int); method public java.lang.String getLine1Number(); - method public java.lang.String getMeid(); - method public java.lang.String getMeid(int); method public java.lang.String getManufacturerCode(); method public java.lang.String getManufacturerCode(int); + method public java.lang.String getMeid(); + method public java.lang.String getMeid(int); method public java.lang.String getMmsUAProfUrl(); method public java.lang.String getMmsUserAgent(); method public java.lang.String getNai(); @@ -42539,6 +42553,8 @@ package android.telephony { method public int getSimState(); method public int getSimState(int); method public java.lang.String getSubscriberId(); + method public java.lang.String getTypeAllocationCode(); + method public java.lang.String getTypeAllocationCode(int); method public java.lang.String getVisualVoicemailPackageName(); method public java.lang.String getVoiceMailAlphaTag(); method public java.lang.String getVoiceMailNumber(); diff --git a/core/java/android/content/ContentProviderClient.java b/core/java/android/content/ContentProviderClient.java index 2d490a03bd76..9d8c318f8092 100644 --- a/core/java/android/content/ContentProviderClient.java +++ b/core/java/android/content/ContentProviderClient.java @@ -39,6 +39,8 @@ import com.android.internal.util.Preconditions; import dalvik.system.CloseGuard; +import libcore.io.IoUtils; + import java.io.FileNotFoundException; import java.util.ArrayList; import java.util.concurrent.atomic.AtomicBoolean; @@ -560,14 +562,17 @@ public class ContentProviderClient implements AutoCloseable { return ContentProvider.coerceToLocalContentProvider(mContentProvider); } + /** + * Closes the given object quietly, ignoring any checked exceptions. Does + * nothing if the given object is {@code null}. + */ + public static void closeQuietly(ContentProviderClient client) { + IoUtils.closeQuietly(client); + } + /** {@hide} */ public static void releaseQuietly(ContentProviderClient client) { - if (client != null) { - try { - client.release(); - } catch (Exception ignored) { - } - } + IoUtils.closeQuietly(client); } private class NotRespondingRunnable implements Runnable { diff --git a/core/java/android/os/FileUtils.java b/core/java/android/os/FileUtils.java index 88d6e847b644..9fccd1ec7b43 100644 --- a/core/java/android/os/FileUtils.java +++ b/core/java/android/os/FileUtils.java @@ -53,32 +53,35 @@ import java.nio.charset.StandardCharsets; import java.util.Arrays; import java.util.Comparator; import java.util.Objects; +import java.util.concurrent.Executor; import java.util.concurrent.TimeUnit; import java.util.regex.Pattern; import java.util.zip.CRC32; import java.util.zip.CheckedInputStream; /** - * Tools for managing files. Not for public consumption. - * @hide + * Utility methods useful for working with files. */ public class FileUtils { private static final String TAG = "FileUtils"; - public static final int S_IRWXU = 00700; - public static final int S_IRUSR = 00400; - public static final int S_IWUSR = 00200; - public static final int S_IXUSR = 00100; + /** {@hide} */ public static final int S_IRWXU = 00700; + /** {@hide} */ public static final int S_IRUSR = 00400; + /** {@hide} */ public static final int S_IWUSR = 00200; + /** {@hide} */ public static final int S_IXUSR = 00100; - public static final int S_IRWXG = 00070; - public static final int S_IRGRP = 00040; - public static final int S_IWGRP = 00020; - public static final int S_IXGRP = 00010; + /** {@hide} */ public static final int S_IRWXG = 00070; + /** {@hide} */ public static final int S_IRGRP = 00040; + /** {@hide} */ public static final int S_IWGRP = 00020; + /** {@hide} */ public static final int S_IXGRP = 00010; - public static final int S_IRWXO = 00007; - public static final int S_IROTH = 00004; - public static final int S_IWOTH = 00002; - public static final int S_IXOTH = 00001; + /** {@hide} */ public static final int S_IRWXO = 00007; + /** {@hide} */ public static final int S_IROTH = 00004; + /** {@hide} */ public static final int S_IWOTH = 00002; + /** {@hide} */ public static final int S_IXOTH = 00001; + + private FileUtils() { + } /** Regular expression for safe filenames: no spaces or metacharacters. * @@ -94,6 +97,9 @@ public class FileUtils { private static final long COPY_CHECKPOINT_BYTES = 524288; + /** + * Listener that is called periodically as progress is made. + */ public interface ProgressListener { public void onProgress(long progress); } @@ -105,6 +111,7 @@ public class FileUtils { * @param uid to apply through {@code chown}, or -1 to leave unchanged * @param gid to apply through {@code chown}, or -1 to leave unchanged * @return 0 on success, otherwise errno. + * @hide */ public static int setPermissions(File path, int mode, int uid, int gid) { return setPermissions(path.getAbsolutePath(), mode, uid, gid); @@ -117,6 +124,7 @@ public class FileUtils { * @param uid to apply through {@code chown}, or -1 to leave unchanged * @param gid to apply through {@code chown}, or -1 to leave unchanged * @return 0 on success, otherwise errno. + * @hide */ public static int setPermissions(String path, int mode, int uid, int gid) { try { @@ -145,6 +153,7 @@ public class FileUtils { * @param uid to apply through {@code chown}, or -1 to leave unchanged * @param gid to apply through {@code chown}, or -1 to leave unchanged * @return 0 on success, otherwise errno. + * @hide */ public static int setPermissions(FileDescriptor fd, int mode, int uid, int gid) { try { @@ -166,7 +175,14 @@ public class FileUtils { return 0; } - public static void copyPermissions(File from, File to) throws IOException { + /** + * Copy the owner UID, owner GID, and mode bits from one file to another. + * + * @param from File where attributes should be copied from. + * @param to File where attributes should be copied to. + * @hide + */ + public static void copyPermissions(@NonNull File from, @NonNull File to) throws IOException { try { final StructStat stat = Os.stat(from.getAbsolutePath()); Os.chmod(to.getAbsolutePath(), stat.st_mode); @@ -177,8 +193,10 @@ public class FileUtils { } /** - * Return owning UID of given path, otherwise -1. + * @deprecated use {@link Os#stat(String)} instead. + * @hide */ + @Deprecated public static int getUid(String path) { try { return Os.stat(path).st_uid; @@ -190,6 +208,8 @@ public class FileUtils { /** * Perform an fsync on the given FileOutputStream. The stream at this * point must be flushed but not yet closed. + * + * @hide */ public static boolean sync(FileOutputStream stream) { try { @@ -204,6 +224,7 @@ public class FileUtils { /** * @deprecated use {@link #copy(File, File)} instead. + * @hide */ @Deprecated public static boolean copyFile(File srcFile, File destFile) { @@ -217,6 +238,7 @@ public class FileUtils { /** * @deprecated use {@link #copy(File, File)} instead. + * @hide */ @Deprecated public static void copyFileOrThrow(File srcFile, File destFile) throws IOException { @@ -227,6 +249,7 @@ public class FileUtils { /** * @deprecated use {@link #copy(InputStream, OutputStream)} instead. + * @hide */ @Deprecated public static boolean copyToFile(InputStream inputStream, File destFile) { @@ -240,6 +263,7 @@ public class FileUtils { /** * @deprecated use {@link #copy(InputStream, OutputStream)} instead. + * @hide */ @Deprecated public static void copyToFileOrThrow(InputStream in, File destFile) throws IOException { @@ -265,7 +289,7 @@ public class FileUtils { * @return number of bytes copied. */ public static long copy(@NonNull File from, @NonNull File to) throws IOException { - return copy(from, to, null, null); + return copy(from, to, null, null, null); } /** @@ -274,16 +298,17 @@ public class FileUtils { * Attempts to use several optimization strategies to copy the data in the * kernel before falling back to a userspace copy as a last resort. * - * @param listener to be periodically notified as the copy progresses. * @param signal to signal if the copy should be cancelled early. + * @param executor that listener events should be delivered via. + * @param listener to be periodically notified as the copy progresses. * @return number of bytes copied. */ public static long copy(@NonNull File from, @NonNull File to, - @Nullable ProgressListener listener, @Nullable CancellationSignal signal) - throws IOException { + @Nullable CancellationSignal signal, @Nullable Executor executor, + @Nullable ProgressListener listener) throws IOException { try (FileInputStream in = new FileInputStream(from); FileOutputStream out = new FileOutputStream(to)) { - return copy(in, out, listener, signal); + return copy(in, out, signal, executor, listener); } } @@ -296,7 +321,7 @@ public class FileUtils { * @return number of bytes copied. */ public static long copy(@NonNull InputStream in, @NonNull OutputStream out) throws IOException { - return copy(in, out, null, null); + return copy(in, out, null, null, null); } /** @@ -305,22 +330,23 @@ public class FileUtils { * Attempts to use several optimization strategies to copy the data in the * kernel before falling back to a userspace copy as a last resort. * - * @param listener to be periodically notified as the copy progresses. * @param signal to signal if the copy should be cancelled early. + * @param executor that listener events should be delivered via. + * @param listener to be periodically notified as the copy progresses. * @return number of bytes copied. */ public static long copy(@NonNull InputStream in, @NonNull OutputStream out, - @Nullable ProgressListener listener, @Nullable CancellationSignal signal) - throws IOException { + @Nullable CancellationSignal signal, @Nullable Executor executor, + @Nullable ProgressListener listener) throws IOException { if (ENABLE_COPY_OPTIMIZATIONS) { if (in instanceof FileInputStream && out instanceof FileOutputStream) { return copy(((FileInputStream) in).getFD(), ((FileOutputStream) out).getFD(), - listener, signal); + signal, executor, listener); } } // Worse case fallback to userspace - return copyInternalUserspace(in, out, listener, signal); + return copyInternalUserspace(in, out, signal, executor, listener); } /** @@ -333,7 +359,7 @@ public class FileUtils { */ public static long copy(@NonNull FileDescriptor in, @NonNull FileDescriptor out) throws IOException { - return copy(in, out, null, null); + return copy(in, out, null, null, null); } /** @@ -342,14 +368,15 @@ public class FileUtils { * Attempts to use several optimization strategies to copy the data in the * kernel before falling back to a userspace copy as a last resort. * - * @param listener to be periodically notified as the copy progresses. * @param signal to signal if the copy should be cancelled early. + * @param executor that listener events should be delivered via. + * @param listener to be periodically notified as the copy progresses. * @return number of bytes copied. */ public static long copy(@NonNull FileDescriptor in, @NonNull FileDescriptor out, - @Nullable ProgressListener listener, @Nullable CancellationSignal signal) - throws IOException { - return copy(in, out, listener, signal, Long.MAX_VALUE); + @Nullable CancellationSignal signal, @Nullable Executor executor, + @Nullable ProgressListener listener) throws IOException { + return copy(in, out, Long.MAX_VALUE, signal, executor, listener); } /** @@ -358,22 +385,24 @@ public class FileUtils { * Attempts to use several optimization strategies to copy the data in the * kernel before falling back to a userspace copy as a last resort. * - * @param listener to be periodically notified as the copy progresses. - * @param signal to signal if the copy should be cancelled early. * @param count the number of bytes to copy. + * @param signal to signal if the copy should be cancelled early. + * @param executor that listener events should be delivered via. + * @param listener to be periodically notified as the copy progresses. * @return number of bytes copied. + * @hide */ - public static long copy(@NonNull FileDescriptor in, @NonNull FileDescriptor out, - @Nullable ProgressListener listener, @Nullable CancellationSignal signal, long count) - throws IOException { + public static long copy(@NonNull FileDescriptor in, @NonNull FileDescriptor out, long count, + @Nullable CancellationSignal signal, @Nullable Executor executor, + @Nullable ProgressListener listener) throws IOException { if (ENABLE_COPY_OPTIMIZATIONS) { try { final StructStat st_in = Os.fstat(in); final StructStat st_out = Os.fstat(out); if (S_ISREG(st_in.st_mode) && S_ISREG(st_out.st_mode)) { - return copyInternalSendfile(in, out, listener, signal, count); + return copyInternalSendfile(in, out, count, signal, executor, listener); } else if (S_ISFIFO(st_in.st_mode) || S_ISFIFO(st_out.st_mode)) { - return copyInternalSplice(in, out, listener, signal, count); + return copyInternalSplice(in, out, count, signal, executor, listener); } } catch (ErrnoException e) { throw e.rethrowAsIOException(); @@ -381,15 +410,17 @@ public class FileUtils { } // Worse case fallback to userspace - return copyInternalUserspace(in, out, listener, signal, count); + return copyInternalUserspace(in, out, count, signal, executor, listener); } /** * Requires one of input or output to be a pipe. + * + * @hide */ @VisibleForTesting - public static long copyInternalSplice(FileDescriptor in, FileDescriptor out, - ProgressListener listener, CancellationSignal signal, long count) + public static long copyInternalSplice(FileDescriptor in, FileDescriptor out, long count, + CancellationSignal signal, Executor executor, ProgressListener listener) throws ErrnoException { long progress = 0; long checkpoint = 0; @@ -405,24 +436,32 @@ public class FileUtils { if (signal != null) { signal.throwIfCanceled(); } - if (listener != null) { - listener.onProgress(progress); + if (executor != null && listener != null) { + final long progressSnapshot = progress; + executor.execute(() -> { + listener.onProgress(progressSnapshot); + }); } checkpoint = 0; } } - if (listener != null) { - listener.onProgress(progress); + if (executor != null && listener != null) { + final long progressSnapshot = progress; + executor.execute(() -> { + listener.onProgress(progressSnapshot); + }); } return progress; } /** * Requires both input and output to be a regular file. + * + * @hide */ @VisibleForTesting - public static long copyInternalSendfile(FileDescriptor in, FileDescriptor out, - ProgressListener listener, CancellationSignal signal, long count) + public static long copyInternalSendfile(FileDescriptor in, FileDescriptor out, long count, + CancellationSignal signal, Executor executor, ProgressListener listener) throws ErrnoException { long progress = 0; long checkpoint = 0; @@ -437,33 +476,52 @@ public class FileUtils { if (signal != null) { signal.throwIfCanceled(); } - if (listener != null) { - listener.onProgress(progress); + if (executor != null && listener != null) { + final long progressSnapshot = progress; + executor.execute(() -> { + listener.onProgress(progressSnapshot); + }); } checkpoint = 0; } } - if (listener != null) { - listener.onProgress(progress); + if (executor != null && listener != null) { + final long progressSnapshot = progress; + executor.execute(() -> { + listener.onProgress(progressSnapshot); + }); } return progress; } + /** {@hide} */ + @Deprecated @VisibleForTesting public static long copyInternalUserspace(FileDescriptor in, FileDescriptor out, - ProgressListener listener, CancellationSignal signal, long count) throws IOException { + ProgressListener listener, CancellationSignal signal, long count) + throws IOException { + return copyInternalUserspace(in, out, count, signal, Runnable::run, listener); + } + + /** {@hide} */ + @VisibleForTesting + public static long copyInternalUserspace(FileDescriptor in, FileDescriptor out, long count, + CancellationSignal signal, Executor executor, ProgressListener listener) + throws IOException { if (count != Long.MAX_VALUE) { return copyInternalUserspace(new SizedInputStream(new FileInputStream(in), count), - new FileOutputStream(out), listener, signal); + new FileOutputStream(out), signal, executor, listener); } else { return copyInternalUserspace(new FileInputStream(in), - new FileOutputStream(out), listener, signal); + new FileOutputStream(out), signal, executor, listener); } } + /** {@hide} */ @VisibleForTesting public static long copyInternalUserspace(InputStream in, OutputStream out, - ProgressListener listener, CancellationSignal signal) throws IOException { + CancellationSignal signal, Executor executor, ProgressListener listener) + throws IOException { long progress = 0; long checkpoint = 0; byte[] buffer = new byte[8192]; @@ -479,14 +537,20 @@ public class FileUtils { if (signal != null) { signal.throwIfCanceled(); } - if (listener != null) { - listener.onProgress(progress); + if (executor != null && listener != null) { + final long progressSnapshot = progress; + executor.execute(() -> { + listener.onProgress(progressSnapshot); + }); } checkpoint = 0; } } - if (listener != null) { - listener.onProgress(progress); + if (executor != null && listener != null) { + final long progressSnapshot = progress; + executor.execute(() -> { + listener.onProgress(progressSnapshot); + }); } return progress; } @@ -494,6 +558,7 @@ public class FileUtils { /** * Check if a filename is "safe" (no metacharacters or spaces). * @param file The file to check + * @hide */ public static boolean isFilenameSafe(File file) { // Note, we check whether it matches what's known to be safe, @@ -509,6 +574,7 @@ public class FileUtils { * @param ellipsis to add of the file was truncated (can be null) * @return the contents of the file, possibly truncated * @throws IOException if something goes wrong reading the file + * @hide */ public static String readTextFile(File file, int max, String ellipsis) throws IOException { InputStream input = new FileInputStream(file); @@ -563,13 +629,16 @@ public class FileUtils { } } + /** {@hide} */ public static void stringToFile(File file, String string) throws IOException { stringToFile(file.getAbsolutePath(), string); } - /* + /** * Writes the bytes given in {@code content} to the file whose absolute path * is {@code filename}. + * + * @hide */ public static void bytesToFile(String filename, byte[] content) throws IOException { if (filename.startsWith("/proc/")) { @@ -592,18 +661,23 @@ public class FileUtils { * @param filename * @param string * @throws IOException + * @hide */ public static void stringToFile(String filename, String string) throws IOException { bytesToFile(filename, string.getBytes(StandardCharsets.UTF_8)); } /** - * Computes the checksum of a file using the CRC32 checksum routine. - * The value of the checksum is returned. + * Computes the checksum of a file using the CRC32 checksum routine. The + * value of the checksum is returned. * - * @param file the file to checksum, must not be null + * @param file the file to checksum, must not be null * @return the checksum value or an exception is thrown. + * @deprecated this is a weak hashing algorithm, and should not be used due + * to its potential for collision. + * @hide */ + @Deprecated public static long checksumCrc32(File file) throws FileNotFoundException, IOException { CRC32 checkSummer = new CRC32(); CheckedInputStream cis = null; @@ -632,6 +706,7 @@ public class FileUtils { * @param minCount Always keep at least this many files. * @param minAgeMs Always keep files younger than this age, in milliseconds. * @return if any files were deleted. + * @hide */ public static boolean deleteOlderFiles(File dir, int minCount, long minAgeMs) { if (minCount < 0 || minAgeMs < 0) { @@ -673,6 +748,8 @@ public class FileUtils { * Both files <em>must</em> have been resolved using * {@link File#getCanonicalFile()} to avoid symlink or path traversal * attacks. + * + * @hide */ public static boolean contains(File[] dirs, File file) { for (File dir : dirs) { @@ -690,12 +767,15 @@ public class FileUtils { * Both files <em>must</em> have been resolved using * {@link File#getCanonicalFile()} to avoid symlink or path traversal * attacks. + * + * @hide */ public static boolean contains(File dir, File file) { if (dir == null || file == null) return false; return contains(dir.getAbsolutePath(), file.getAbsolutePath()); } + /** {@hide} */ public static boolean contains(String dirPath, String filePath) { if (dirPath.equals(filePath)) { return true; @@ -706,6 +786,7 @@ public class FileUtils { return filePath.startsWith(dirPath); } + /** {@hide} */ public static boolean deleteContentsAndDir(File dir) { if (deleteContents(dir)) { return dir.delete(); @@ -714,6 +795,7 @@ public class FileUtils { } } + /** {@hide} */ public static boolean deleteContents(File dir) { File[] files = dir.listFiles(); boolean success = true; @@ -743,6 +825,8 @@ public class FileUtils { /** * Check if given filename is valid for an ext4 filesystem. + * + * @hide */ public static boolean isValidExtFilename(String name) { return (name != null) && name.equals(buildValidExtFilename(name)); @@ -751,6 +835,8 @@ public class FileUtils { /** * Mutate the given filename to make it valid for an ext4 filesystem, * replacing any invalid characters with "_". + * + * @hide */ public static String buildValidExtFilename(String name) { if (TextUtils.isEmpty(name) || ".".equals(name) || "..".equals(name)) { @@ -792,6 +878,8 @@ public class FileUtils { /** * Check if given filename is valid for a FAT filesystem. + * + * @hide */ public static boolean isValidFatFilename(String name) { return (name != null) && name.equals(buildValidFatFilename(name)); @@ -800,6 +888,8 @@ public class FileUtils { /** * Mutate the given filename to make it valid for a FAT filesystem, * replacing any invalid characters with "_". + * + * @hide */ public static String buildValidFatFilename(String name) { if (TextUtils.isEmpty(name) || ".".equals(name) || "..".equals(name)) { @@ -820,6 +910,7 @@ public class FileUtils { return res.toString(); } + /** {@hide} */ @VisibleForTesting public static String trimFilename(String str, int maxBytes) { final StringBuilder res = new StringBuilder(str); @@ -827,6 +918,7 @@ public class FileUtils { return res.toString(); } + /** {@hide} */ private static void trimFilename(StringBuilder res, int maxBytes) { byte[] raw = res.toString().getBytes(StandardCharsets.UTF_8); if (raw.length > maxBytes) { @@ -839,12 +931,14 @@ public class FileUtils { } } + /** {@hide} */ public static String rewriteAfterRename(File beforeDir, File afterDir, String path) { if (path == null) return null; final File result = rewriteAfterRename(beforeDir, afterDir, new File(path)); return (result != null) ? result.getAbsolutePath() : null; } + /** {@hide} */ public static String[] rewriteAfterRename(File beforeDir, File afterDir, String[] paths) { if (paths == null) return null; final String[] result = new String[paths.length]; @@ -858,6 +952,8 @@ public class FileUtils { * Given a path under the "before" directory, rewrite it to live under the * "after" directory. For example, {@code /before/foo/bar.txt} would become * {@code /after/foo/bar.txt}. + * + * @hide */ public static File rewriteAfterRename(File beforeDir, File afterDir, File file) { if (file == null || beforeDir == null || afterDir == null) return null; @@ -869,6 +965,7 @@ public class FileUtils { return null; } + /** {@hide} */ private static File buildUniqueFileWithExtension(File parent, String name, String ext) throws FileNotFoundException { File file = buildFile(parent, name, ext); @@ -895,6 +992,7 @@ public class FileUtils { * 'example.txt' or 'example (1).txt', etc. * * @throws FileNotFoundException + * @hide */ public static File buildUniqueFile(File parent, String mimeType, String displayName) throws FileNotFoundException { @@ -905,6 +1003,8 @@ public class FileUtils { /** * Generates a unique file name under the given parent directory, keeping * any extension intact. + * + * @hide */ public static File buildUniqueFile(File parent, String displayName) throws FileNotFoundException { @@ -929,6 +1029,8 @@ public class FileUtils { * If the display name doesn't have an extension that matches the requested MIME type, the * extension is regarded as a part of filename and default extension for that MIME type is * appended. + * + * @hide */ public static String[] splitFileName(String mimeType, String displayName) { String name; @@ -975,6 +1077,7 @@ public class FileUtils { return new String[] { name, ext }; } + /** {@hide} */ private static File buildFile(File parent, String name, String ext) { if (TextUtils.isEmpty(ext)) { return new File(parent, name); @@ -983,6 +1086,7 @@ public class FileUtils { } } + /** {@hide} */ public static @NonNull String[] listOrEmpty(@Nullable File dir) { if (dir == null) return EmptyArray.STRING; final String[] res = dir.list(); @@ -993,6 +1097,7 @@ public class FileUtils { } } + /** {@hide} */ public static @NonNull File[] listFilesOrEmpty(@Nullable File dir) { if (dir == null) return EMPTY; final File[] res = dir.listFiles(); @@ -1003,6 +1108,7 @@ public class FileUtils { } } + /** {@hide} */ public static @NonNull File[] listFilesOrEmpty(@Nullable File dir, FilenameFilter filter) { if (dir == null) return EMPTY; final File[] res = dir.listFiles(filter); @@ -1013,6 +1119,7 @@ public class FileUtils { } } + /** {@hide} */ public static @Nullable File newFileOrNull(@Nullable String path) { return (path != null) ? new File(path) : null; } @@ -1021,6 +1128,8 @@ public class FileUtils { * Creates a directory with name {@code name} under an existing directory {@code baseDir}. * Returns a {@code File} object representing the directory on success, {@code null} on * failure. + * + * @hide */ public static @Nullable File createDir(File baseDir, String name) { final File dir = new File(baseDir, name); @@ -1036,6 +1145,8 @@ public class FileUtils { * Round the given size of a storage device to a nice round power-of-two * value, such as 256MB or 32GB. This avoids showing weird values like * "29.5GB" in UI. + * + * @hide */ public static long roundStorageSize(long size) { long val = 1; @@ -1050,6 +1161,23 @@ public class FileUtils { return val * pow; } + /** + * Closes the given object quietly, ignoring any checked exceptions. Does + * nothing if the given object is {@code null}. + */ + public static void closeQuietly(@Nullable AutoCloseable closeable) { + IoUtils.closeQuietly(closeable); + } + + /** + * Closes the given object quietly, ignoring any checked exceptions. Does + * nothing if the given object is {@code null}. + */ + public static void closeQuietly(@Nullable FileDescriptor fd) { + IoUtils.closeQuietly(fd); + } + + /** {@hide} */ @VisibleForTesting public static class MemoryPipe extends Thread implements AutoCloseable { private final FileDescriptor[] pipe; diff --git a/core/java/android/print/PrintFileDocumentAdapter.java b/core/java/android/print/PrintFileDocumentAdapter.java index a5f93050e307..eb4b31510880 100644 --- a/core/java/android/print/PrintFileDocumentAdapter.java +++ b/core/java/android/print/PrintFileDocumentAdapter.java @@ -118,7 +118,7 @@ public class PrintFileDocumentAdapter extends PrintDocumentAdapter { protected Void doInBackground(Void... params) { try (InputStream in = new FileInputStream(mFile); OutputStream out = new FileOutputStream(mDestination.getFileDescriptor())) { - FileUtils.copy(in, out, null, mCancellationSignal); + FileUtils.copy(in, out, mCancellationSignal, null, null); } catch (OperationCanceledException e) { // Ignored; already handled below } catch (IOException e) { diff --git a/core/java/android/provider/DocumentsContract.java b/core/java/android/provider/DocumentsContract.java index a80dcedf9915..f97c64c96a7a 100644 --- a/core/java/android/provider/DocumentsContract.java +++ b/core/java/android/provider/DocumentsContract.java @@ -100,7 +100,8 @@ public final class DocumentsContract { public static final String PROVIDER_INTERFACE = "android.content.action.DOCUMENTS_PROVIDER"; /** {@hide} */ - public static final String EXTRA_PACKAGE_NAME = "android.content.extra.PACKAGE_NAME"; + @Deprecated + public static final String EXTRA_PACKAGE_NAME = Intent.EXTRA_PACKAGE_NAME; /** {@hide} */ public static final String EXTRA_SHOW_ADVANCED = "android.content.extra.SHOW_ADVANCED"; diff --git a/core/tests/benchmarks/src/android/os/FileUtilsBenchmark.java b/core/tests/benchmarks/src/android/os/FileUtilsBenchmark.java index 5989da7af655..c70fc3cce43c 100644 --- a/core/tests/benchmarks/src/android/os/FileUtilsBenchmark.java +++ b/core/tests/benchmarks/src/android/os/FileUtilsBenchmark.java @@ -54,7 +54,7 @@ public class FileUtilsBenchmark { for (int i = 0; i < reps; i++) { try (FileInputStream in = new FileInputStream(mSrc); FileOutputStream out = new FileOutputStream(mDest)) { - copyInternalUserspace(in.getFD(), out.getFD(), null, null, Long.MAX_VALUE); + copyInternalUserspace(in.getFD(), out.getFD(), Long.MAX_VALUE, null, null, null); } } } @@ -63,7 +63,7 @@ public class FileUtilsBenchmark { for (int i = 0; i < reps; i++) { try (FileInputStream in = new FileInputStream(mSrc); FileOutputStream out = new FileOutputStream(mDest)) { - copyInternalSendfile(in.getFD(), out.getFD(), null, null, Long.MAX_VALUE); + copyInternalSendfile(in.getFD(), out.getFD(), Long.MAX_VALUE, null, null, null); } } } @@ -72,7 +72,7 @@ public class FileUtilsBenchmark { for (int i = 0; i < reps; i++) { try (MemoryPipe in = MemoryPipe.createSource(mData); FileOutputStream out = new FileOutputStream(mDest)) { - copyInternalUserspace(in.getFD(), out.getFD(), null, null, Long.MAX_VALUE); + copyInternalUserspace(in.getFD(), out.getFD(), Long.MAX_VALUE, null, null, null); } } } @@ -81,7 +81,7 @@ public class FileUtilsBenchmark { for (int i = 0; i < reps; i++) { try (MemoryPipe in = MemoryPipe.createSource(mData); FileOutputStream out = new FileOutputStream(mDest)) { - copyInternalSplice(in.getFD(), out.getFD(), null, null, Long.MAX_VALUE); + copyInternalSplice(in.getFD(), out.getFD(), Long.MAX_VALUE, null, null, null); } } } @@ -90,7 +90,7 @@ public class FileUtilsBenchmark { for (int i = 0; i < reps; i++) { try (FileInputStream in = new FileInputStream(mSrc); MemoryPipe out = MemoryPipe.createSink(mData)) { - copyInternalUserspace(in.getFD(), out.getFD(), null, null, Long.MAX_VALUE); + copyInternalUserspace(in.getFD(), out.getFD(), Long.MAX_VALUE, null, null, null); } } } @@ -99,7 +99,7 @@ public class FileUtilsBenchmark { for (int i = 0; i < reps; i++) { try (FileInputStream in = new FileInputStream(mSrc); MemoryPipe out = MemoryPipe.createSink(mData)) { - copyInternalSplice(in.getFD(), out.getFD(), null, null, Long.MAX_VALUE); + copyInternalSplice(in.getFD(), out.getFD(), Long.MAX_VALUE, null, null, null); } } } diff --git a/core/tests/coretests/src/android/os/FileUtilsTest.java b/core/tests/coretests/src/android/os/FileUtilsTest.java index 0bc3a2d879ab..9c9f11b76ab4 100644 --- a/core/tests/coretests/src/android/os/FileUtilsTest.java +++ b/core/tests/coretests/src/android/os/FileUtilsTest.java @@ -193,7 +193,7 @@ public class FileUtilsTest { try (MemoryPipe in = MemoryPipe.createSource(source); FileOutputStream out = new FileOutputStream(dest)) { - FileUtils.copy(in.getFD(), out.getFD(), null, null, size); + FileUtils.copy(in.getFD(), out.getFD(), size, null, null, null); } actual = readFile(dest); diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java index 06fbf9f6e1c1..59f272ff70f6 100644 --- a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java +++ b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java @@ -297,7 +297,7 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat + " cannot be null"); } - mCallingPackageName = extras.getString(DocumentsContract.EXTRA_PACKAGE_NAME); + mCallingPackageName = extras.getString(Intent.EXTRA_PACKAGE_NAME); if (savedInstanceState == null) { MetricsLogger.action(this, MetricsEvent.PRINT_PREVIEW, mCallingPackageName); @@ -715,7 +715,7 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT); intent.setType("application/pdf"); intent.putExtra(Intent.EXTRA_TITLE, info.getName()); - intent.putExtra(DocumentsContract.EXTRA_PACKAGE_NAME, mCallingPackageName); + intent.putExtra(Intent.EXTRA_PACKAGE_NAME, mCallingPackageName); try { startActivityForResult(intent, ACTIVITY_REQUEST_CREATE_FILE); diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java index fa934fe23fff..9b6850b3c798 100644 --- a/services/core/java/com/android/server/pm/PackageInstallerSession.java +++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java @@ -685,13 +685,14 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { // inserted above to hold the session active. try { final Int64Ref last = new Int64Ref(0); - FileUtils.copy(incomingFd.getFileDescriptor(), targetFd, (long progress) -> { - if (params.sizeBytes > 0) { - final long delta = progress - last.value; - last.value = progress; - addClientProgress((float) delta / (float) params.sizeBytes); - } - }, null, lengthBytes); + FileUtils.copy(incomingFd.getFileDescriptor(), targetFd, lengthBytes, null, + Runnable::run, (long progress) -> { + if (params.sizeBytes > 0) { + final long delta = progress - last.value; + last.value = progress; + addClientProgress((float) delta / (float) params.sizeBytes); + } + }); } finally { IoUtils.closeQuietly(targetFd); IoUtils.closeQuietly(incomingFd); diff --git a/services/print/java/com/android/server/print/UserState.java b/services/print/java/com/android/server/print/UserState.java index 4fbc14c0097f..e8266a574bf5 100644 --- a/services/print/java/com/android/server/print/UserState.java +++ b/services/print/java/com/android/server/print/UserState.java @@ -243,7 +243,7 @@ final class UserState implements PrintSpoolerCallbacks, PrintServiceCallbacks, intent.setData(Uri.fromParts("printjob", printJob.getId().flattenToString(), null)); intent.putExtra(PrintManager.EXTRA_PRINT_DOCUMENT_ADAPTER, adapter.asBinder()); intent.putExtra(PrintManager.EXTRA_PRINT_JOB, printJob); - intent.putExtra(DocumentsContract.EXTRA_PACKAGE_NAME, packageName); + intent.putExtra(Intent.EXTRA_PACKAGE_NAME, packageName); IntentSender intentSender = PendingIntent.getActivityAsUser( mContext, 0, intent, PendingIntent.FLAG_ONE_SHOT |