Loading api/current.txt +8 −0 Original line number Diff line number Diff line Loading @@ -30466,14 +30466,22 @@ package android.os.storage { } public class StorageManager { method public long getCacheQuotaBytes(); method public long getCacheSizeBytes(); method public long getExternalCacheQuotaBytes(); method public long getExternalCacheSizeBytes(); method public java.lang.String getMountedObbPath(java.lang.String); method public android.os.storage.StorageVolume getPrimaryStorageVolume(); method public android.os.storage.StorageVolume getStorageVolume(java.io.File); method public java.util.List<android.os.storage.StorageVolume> getStorageVolumes(); method public boolean isCacheBehaviorAtomic(java.io.File) throws java.io.IOException; method public boolean isCacheBehaviorTombstone(java.io.File) throws java.io.IOException; method public boolean isEncrypted(java.io.File); method public boolean isObbMounted(java.lang.String); method public boolean mountObb(java.lang.String, java.lang.String, android.os.storage.OnObbStateChangeListener); method public android.os.ParcelFileDescriptor openProxyFileDescriptor(int, android.os.ProxyFileDescriptorCallback) throws java.io.IOException; method public void setCacheBehaviorAtomic(java.io.File, boolean) throws java.io.IOException; method public void setCacheBehaviorTombstone(java.io.File, boolean) throws java.io.IOException; method public boolean unmountObb(java.lang.String, boolean, android.os.storage.OnObbStateChangeListener); field public static final java.lang.String ACTION_MANAGE_STORAGE = "android.os.storage.action.MANAGE_STORAGE"; } api/system-current.txt +8 −0 Original line number Diff line number Diff line Loading @@ -33220,14 +33220,22 @@ package android.os.storage { } public class StorageManager { method public long getCacheQuotaBytes(); method public long getCacheSizeBytes(); method public long getExternalCacheQuotaBytes(); method public long getExternalCacheSizeBytes(); method public java.lang.String getMountedObbPath(java.lang.String); method public android.os.storage.StorageVolume getPrimaryStorageVolume(); method public android.os.storage.StorageVolume getStorageVolume(java.io.File); method public java.util.List<android.os.storage.StorageVolume> getStorageVolumes(); method public boolean isCacheBehaviorAtomic(java.io.File) throws java.io.IOException; method public boolean isCacheBehaviorTombstone(java.io.File) throws java.io.IOException; method public boolean isEncrypted(java.io.File); method public boolean isObbMounted(java.lang.String); method public boolean mountObb(java.lang.String, java.lang.String, android.os.storage.OnObbStateChangeListener); method public android.os.ParcelFileDescriptor openProxyFileDescriptor(int, android.os.ProxyFileDescriptorCallback) throws java.io.IOException; method public void setCacheBehaviorAtomic(java.io.File, boolean) throws java.io.IOException; method public void setCacheBehaviorTombstone(java.io.File, boolean) throws java.io.IOException; method public boolean unmountObb(java.lang.String, boolean, android.os.storage.OnObbStateChangeListener); field public static final java.lang.String ACTION_MANAGE_STORAGE = "android.os.storage.action.MANAGE_STORAGE"; } api/test-current.txt +8 −0 Original line number Diff line number Diff line Loading @@ -30579,14 +30579,22 @@ package android.os.storage { } public class StorageManager { method public long getCacheQuotaBytes(); method public long getCacheSizeBytes(); method public long getExternalCacheQuotaBytes(); method public long getExternalCacheSizeBytes(); method public java.lang.String getMountedObbPath(java.lang.String); method public android.os.storage.StorageVolume getPrimaryStorageVolume(); method public android.os.storage.StorageVolume getStorageVolume(java.io.File); method public java.util.List<android.os.storage.StorageVolume> getStorageVolumes(); method public boolean isCacheBehaviorAtomic(java.io.File) throws java.io.IOException; method public boolean isCacheBehaviorTombstone(java.io.File) throws java.io.IOException; method public boolean isEncrypted(java.io.File); method public boolean isObbMounted(java.lang.String); method public boolean mountObb(java.lang.String, java.lang.String, android.os.storage.OnObbStateChangeListener); method public android.os.ParcelFileDescriptor openProxyFileDescriptor(int, android.os.ProxyFileDescriptorCallback) throws java.io.IOException; method public void setCacheBehaviorAtomic(java.io.File, boolean) throws java.io.IOException; method public void setCacheBehaviorTombstone(java.io.File, boolean) throws java.io.IOException; method public boolean unmountObb(java.lang.String, boolean, android.os.storage.OnObbStateChangeListener); field public static final java.lang.String ACTION_MANAGE_STORAGE = "android.os.storage.action.MANAGE_STORAGE"; } core/java/android/os/storage/IStorageManager.aidl +2 −0 Original line number Diff line number Diff line Loading @@ -291,4 +291,6 @@ interface IStorageManager { void fstrim(int flags) = 72; AppFuseMount mountProxyFileDescriptorBridge() = 73; ParcelFileDescriptor openProxyFileDescriptor(int mountPointId, int fileId, int mode) = 74; long getCacheQuotaBytes(String volumeUuid, int uid) = 75; long getCacheSizeBytes(String volumeUuid, int uid) = 76; } core/java/android/os/storage/StorageManager.java +223 −1 Original line number Diff line number Diff line Loading @@ -24,27 +24,32 @@ import android.annotation.SdkConstant; import android.app.ActivityThread; import android.content.ContentResolver; import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.IPackageMoveObserver; import android.content.pm.PackageManager; import android.os.Binder; import android.os.Environment; import android.os.FileUtils; import android.os.Handler; import android.os.ProxyFileDescriptorCallback; import android.os.Looper; import android.os.Message; import android.os.ParcelFileDescriptor; import android.os.ProxyFileDescriptorCallback; import android.os.RemoteException; import android.os.ServiceManager; import android.os.ServiceManager.ServiceNotFoundException; import android.os.SystemProperties; import android.os.UserHandle; import android.provider.Settings; import android.system.ErrnoException; import android.system.Os; import android.system.OsConstants; import android.text.TextUtils; import android.util.Log; import android.util.Pair; import android.util.Slog; import android.util.SparseArray; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.os.AppFuseMount; Loading @@ -60,6 +65,7 @@ import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStreamReader; import java.lang.ref.WeakReference; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; Loading Loading @@ -1396,6 +1402,222 @@ public class StorageManager { } } /** * Return quota size in bytes for cached data belonging to the calling app. * <p> * If your app goes above this quota, your cached files will be some of the * first to be deleted when additional disk space is needed. Conversely, if * your app stays under this quota, your cached files will be some of the * last to be deleted when additional disk space is needed. * <p> * This quota may change over time depending on how frequently the user * interacts with your app, and depending on how much disk space is used. * <p> * Cached data tracked by this method always includes * {@link Context#getCacheDir()} and {@link Context#getCodeCacheDir()}, and * it also includes {@link Context#getExternalCacheDir()} if the primary * shared/external storage is hosted on the same storage device as your * private data. * <p class="note"> * Note: if your app uses the {@code android:sharedUserId} manifest feature, * then cached data for all packages in your shared UID is tracked together * as a single unit. * </p> * * @see #getCacheQuotaBytes() * @see #getCacheSizeBytes() * @see #getExternalCacheQuotaBytes() * @see #getExternalCacheSizeBytes() */ public long getCacheQuotaBytes() { try { final ApplicationInfo app = mContext.getApplicationInfo(); return mStorageManager.getCacheQuotaBytes(app.volumeUuid, app.uid); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * Return total size in bytes of cached data belonging to the calling app. * <p> * Cached data tracked by this method always includes * {@link Context#getCacheDir()} and {@link Context#getCodeCacheDir()}, and * it also includes {@link Context#getExternalCacheDir()} if the primary * shared/external storage is hosted on the same storage device as your * private data. * <p class="note"> * Note: if your app uses the {@code android:sharedUserId} manifest feature, * then cached data for all packages in your shared UID is tracked together * as a single unit. * </p> * * @see #getCacheQuotaBytes() * @see #getCacheSizeBytes() * @see #getExternalCacheQuotaBytes() * @see #getExternalCacheSizeBytes() */ public long getCacheSizeBytes() { try { final ApplicationInfo app = mContext.getApplicationInfo(); return mStorageManager.getCacheSizeBytes(app.volumeUuid, app.uid); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * Return quota size in bytes for cached data on primary shared/external * storage belonging to the calling app. * <p> * If primary shared/external storage is hosted on the same storage device * as your private data, this method will return -1, since all data stored * under {@link Context#getExternalCacheDir()} will be counted under * {@link #getCacheQuotaBytes()}. * <p class="note"> * Note: if your app uses the {@code android:sharedUserId} manifest feature, * then cached data for all packages in your shared UID is tracked together * as a single unit. * </p> */ public long getExternalCacheQuotaBytes() { final ApplicationInfo app = mContext.getApplicationInfo(); final String primaryUuid = getPrimaryStorageUuid(); if (Objects.equals(app.volumeUuid, primaryUuid)) { return -1; } try { return mStorageManager.getCacheQuotaBytes(primaryUuid, app.uid); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * Return total size in bytes of cached data on primary shared/external * storage belonging to the calling app. * <p> * If primary shared/external storage is hosted on the same storage device * as your private data, this method will return -1, since all data stored * under {@link Context#getExternalCacheDir()} will be counted under * {@link #getCacheQuotaBytes()}. * <p class="note"> * Note: if your app uses the {@code android:sharedUserId} manifest feature, * then cached data for all packages in your shared UID is tracked together * as a single unit. * </p> */ public long getExternalCacheSizeBytes() { final ApplicationInfo app = mContext.getApplicationInfo(); final String primaryUuid = getPrimaryStorageUuid(); if (Objects.equals(app.volumeUuid, primaryUuid)) { return -1; } try { return mStorageManager.getCacheSizeBytes(primaryUuid, app.uid); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } private static final String XATTR_ATOMIC = "user.atomic"; private static final String XATTR_TOMBSTONE = "user.tombstone"; /** {@hide} */ private static void setCacheBehavior(File path, String name, boolean enabled) throws IOException { if (!path.isDirectory()) { throw new IOException("Cache behavior can only be set on directories"); } if (enabled) { try { Os.setxattr(path.getAbsolutePath(), name, "1".getBytes(StandardCharsets.UTF_8), 0); } catch (ErrnoException e) { throw e.rethrowAsIOException(); } } else { try { Os.removexattr(path.getAbsolutePath(), name); } catch (ErrnoException e) { if (e.errno != OsConstants.ENODATA) { throw e.rethrowAsIOException(); } } } } /** {@hide} */ private static boolean isCacheBehavior(File path, String name) throws IOException { try { Os.getxattr(path.getAbsolutePath(), name); return true; } catch (ErrnoException e) { if (e.errno != OsConstants.ENODATA) { throw e.rethrowAsIOException(); } else { return false; } } } /** * Enable or disable special cache behavior that treats this directory and * its contents as an atomic unit. * <p> * When enabled and this directory is considered for automatic deletion by * the OS, all contained files will either be deleted together, or not at * all. This is useful when you have a directory that contains several * related metadata files that depend on each other, such as movie file and * a subtitle file. * <p> * When enabled, the <em>newest</em> {@link File#lastModified()} value of * any contained files is considered the modified time of the entire * directory. * <p> * This behavior can only be set on a directory, and it applies recursively * to all contained files and directories. */ public void setCacheBehaviorAtomic(File path, boolean atomic) throws IOException { setCacheBehavior(path, XATTR_ATOMIC, atomic); } /** * Read the current value set by * {@link #setCacheBehaviorAtomic(File, boolean)}. */ public boolean isCacheBehaviorAtomic(File path) throws IOException { return isCacheBehavior(path, XATTR_ATOMIC); } /** * Enable or disable special cache behavior that leaves deleted cache files * intact as tombstones. * <p> * When enabled and a file contained in this directory is automatically * deleted by the OS, the file will be truncated to have a length of 0 bytes * instead of being fully deleted. This is useful if you need to distinguish * between a file that was deleted versus one that never existed. * <p> * This behavior can only be set on a directory, and it applies recursively * to all contained files and directories. * <p class="note"> * Note: this behavior is ignored completely if the user explicitly requests * that all cached data be cleared. * </p> */ public void setCacheBehaviorTombstone(File path, boolean tombstone) throws IOException { setCacheBehavior(path, XATTR_TOMBSTONE, tombstone); } /** * Read the current value set by * {@link #setCacheBehaviorTombstone(File, boolean)}. */ public boolean isCacheBehaviorTombstone(File path) throws IOException { return isCacheBehavior(path, XATTR_TOMBSTONE); } private final Object mFuseAppLoopLock = new Object(); @GuardedBy("mFuseAppLoopLock") Loading Loading
api/current.txt +8 −0 Original line number Diff line number Diff line Loading @@ -30466,14 +30466,22 @@ package android.os.storage { } public class StorageManager { method public long getCacheQuotaBytes(); method public long getCacheSizeBytes(); method public long getExternalCacheQuotaBytes(); method public long getExternalCacheSizeBytes(); method public java.lang.String getMountedObbPath(java.lang.String); method public android.os.storage.StorageVolume getPrimaryStorageVolume(); method public android.os.storage.StorageVolume getStorageVolume(java.io.File); method public java.util.List<android.os.storage.StorageVolume> getStorageVolumes(); method public boolean isCacheBehaviorAtomic(java.io.File) throws java.io.IOException; method public boolean isCacheBehaviorTombstone(java.io.File) throws java.io.IOException; method public boolean isEncrypted(java.io.File); method public boolean isObbMounted(java.lang.String); method public boolean mountObb(java.lang.String, java.lang.String, android.os.storage.OnObbStateChangeListener); method public android.os.ParcelFileDescriptor openProxyFileDescriptor(int, android.os.ProxyFileDescriptorCallback) throws java.io.IOException; method public void setCacheBehaviorAtomic(java.io.File, boolean) throws java.io.IOException; method public void setCacheBehaviorTombstone(java.io.File, boolean) throws java.io.IOException; method public boolean unmountObb(java.lang.String, boolean, android.os.storage.OnObbStateChangeListener); field public static final java.lang.String ACTION_MANAGE_STORAGE = "android.os.storage.action.MANAGE_STORAGE"; }
api/system-current.txt +8 −0 Original line number Diff line number Diff line Loading @@ -33220,14 +33220,22 @@ package android.os.storage { } public class StorageManager { method public long getCacheQuotaBytes(); method public long getCacheSizeBytes(); method public long getExternalCacheQuotaBytes(); method public long getExternalCacheSizeBytes(); method public java.lang.String getMountedObbPath(java.lang.String); method public android.os.storage.StorageVolume getPrimaryStorageVolume(); method public android.os.storage.StorageVolume getStorageVolume(java.io.File); method public java.util.List<android.os.storage.StorageVolume> getStorageVolumes(); method public boolean isCacheBehaviorAtomic(java.io.File) throws java.io.IOException; method public boolean isCacheBehaviorTombstone(java.io.File) throws java.io.IOException; method public boolean isEncrypted(java.io.File); method public boolean isObbMounted(java.lang.String); method public boolean mountObb(java.lang.String, java.lang.String, android.os.storage.OnObbStateChangeListener); method public android.os.ParcelFileDescriptor openProxyFileDescriptor(int, android.os.ProxyFileDescriptorCallback) throws java.io.IOException; method public void setCacheBehaviorAtomic(java.io.File, boolean) throws java.io.IOException; method public void setCacheBehaviorTombstone(java.io.File, boolean) throws java.io.IOException; method public boolean unmountObb(java.lang.String, boolean, android.os.storage.OnObbStateChangeListener); field public static final java.lang.String ACTION_MANAGE_STORAGE = "android.os.storage.action.MANAGE_STORAGE"; }
api/test-current.txt +8 −0 Original line number Diff line number Diff line Loading @@ -30579,14 +30579,22 @@ package android.os.storage { } public class StorageManager { method public long getCacheQuotaBytes(); method public long getCacheSizeBytes(); method public long getExternalCacheQuotaBytes(); method public long getExternalCacheSizeBytes(); method public java.lang.String getMountedObbPath(java.lang.String); method public android.os.storage.StorageVolume getPrimaryStorageVolume(); method public android.os.storage.StorageVolume getStorageVolume(java.io.File); method public java.util.List<android.os.storage.StorageVolume> getStorageVolumes(); method public boolean isCacheBehaviorAtomic(java.io.File) throws java.io.IOException; method public boolean isCacheBehaviorTombstone(java.io.File) throws java.io.IOException; method public boolean isEncrypted(java.io.File); method public boolean isObbMounted(java.lang.String); method public boolean mountObb(java.lang.String, java.lang.String, android.os.storage.OnObbStateChangeListener); method public android.os.ParcelFileDescriptor openProxyFileDescriptor(int, android.os.ProxyFileDescriptorCallback) throws java.io.IOException; method public void setCacheBehaviorAtomic(java.io.File, boolean) throws java.io.IOException; method public void setCacheBehaviorTombstone(java.io.File, boolean) throws java.io.IOException; method public boolean unmountObb(java.lang.String, boolean, android.os.storage.OnObbStateChangeListener); field public static final java.lang.String ACTION_MANAGE_STORAGE = "android.os.storage.action.MANAGE_STORAGE"; }
core/java/android/os/storage/IStorageManager.aidl +2 −0 Original line number Diff line number Diff line Loading @@ -291,4 +291,6 @@ interface IStorageManager { void fstrim(int flags) = 72; AppFuseMount mountProxyFileDescriptorBridge() = 73; ParcelFileDescriptor openProxyFileDescriptor(int mountPointId, int fileId, int mode) = 74; long getCacheQuotaBytes(String volumeUuid, int uid) = 75; long getCacheSizeBytes(String volumeUuid, int uid) = 76; }
core/java/android/os/storage/StorageManager.java +223 −1 Original line number Diff line number Diff line Loading @@ -24,27 +24,32 @@ import android.annotation.SdkConstant; import android.app.ActivityThread; import android.content.ContentResolver; import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.IPackageMoveObserver; import android.content.pm.PackageManager; import android.os.Binder; import android.os.Environment; import android.os.FileUtils; import android.os.Handler; import android.os.ProxyFileDescriptorCallback; import android.os.Looper; import android.os.Message; import android.os.ParcelFileDescriptor; import android.os.ProxyFileDescriptorCallback; import android.os.RemoteException; import android.os.ServiceManager; import android.os.ServiceManager.ServiceNotFoundException; import android.os.SystemProperties; import android.os.UserHandle; import android.provider.Settings; import android.system.ErrnoException; import android.system.Os; import android.system.OsConstants; import android.text.TextUtils; import android.util.Log; import android.util.Pair; import android.util.Slog; import android.util.SparseArray; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.os.AppFuseMount; Loading @@ -60,6 +65,7 @@ import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStreamReader; import java.lang.ref.WeakReference; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; Loading Loading @@ -1396,6 +1402,222 @@ public class StorageManager { } } /** * Return quota size in bytes for cached data belonging to the calling app. * <p> * If your app goes above this quota, your cached files will be some of the * first to be deleted when additional disk space is needed. Conversely, if * your app stays under this quota, your cached files will be some of the * last to be deleted when additional disk space is needed. * <p> * This quota may change over time depending on how frequently the user * interacts with your app, and depending on how much disk space is used. * <p> * Cached data tracked by this method always includes * {@link Context#getCacheDir()} and {@link Context#getCodeCacheDir()}, and * it also includes {@link Context#getExternalCacheDir()} if the primary * shared/external storage is hosted on the same storage device as your * private data. * <p class="note"> * Note: if your app uses the {@code android:sharedUserId} manifest feature, * then cached data for all packages in your shared UID is tracked together * as a single unit. * </p> * * @see #getCacheQuotaBytes() * @see #getCacheSizeBytes() * @see #getExternalCacheQuotaBytes() * @see #getExternalCacheSizeBytes() */ public long getCacheQuotaBytes() { try { final ApplicationInfo app = mContext.getApplicationInfo(); return mStorageManager.getCacheQuotaBytes(app.volumeUuid, app.uid); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * Return total size in bytes of cached data belonging to the calling app. * <p> * Cached data tracked by this method always includes * {@link Context#getCacheDir()} and {@link Context#getCodeCacheDir()}, and * it also includes {@link Context#getExternalCacheDir()} if the primary * shared/external storage is hosted on the same storage device as your * private data. * <p class="note"> * Note: if your app uses the {@code android:sharedUserId} manifest feature, * then cached data for all packages in your shared UID is tracked together * as a single unit. * </p> * * @see #getCacheQuotaBytes() * @see #getCacheSizeBytes() * @see #getExternalCacheQuotaBytes() * @see #getExternalCacheSizeBytes() */ public long getCacheSizeBytes() { try { final ApplicationInfo app = mContext.getApplicationInfo(); return mStorageManager.getCacheSizeBytes(app.volumeUuid, app.uid); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * Return quota size in bytes for cached data on primary shared/external * storage belonging to the calling app. * <p> * If primary shared/external storage is hosted on the same storage device * as your private data, this method will return -1, since all data stored * under {@link Context#getExternalCacheDir()} will be counted under * {@link #getCacheQuotaBytes()}. * <p class="note"> * Note: if your app uses the {@code android:sharedUserId} manifest feature, * then cached data for all packages in your shared UID is tracked together * as a single unit. * </p> */ public long getExternalCacheQuotaBytes() { final ApplicationInfo app = mContext.getApplicationInfo(); final String primaryUuid = getPrimaryStorageUuid(); if (Objects.equals(app.volumeUuid, primaryUuid)) { return -1; } try { return mStorageManager.getCacheQuotaBytes(primaryUuid, app.uid); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * Return total size in bytes of cached data on primary shared/external * storage belonging to the calling app. * <p> * If primary shared/external storage is hosted on the same storage device * as your private data, this method will return -1, since all data stored * under {@link Context#getExternalCacheDir()} will be counted under * {@link #getCacheQuotaBytes()}. * <p class="note"> * Note: if your app uses the {@code android:sharedUserId} manifest feature, * then cached data for all packages in your shared UID is tracked together * as a single unit. * </p> */ public long getExternalCacheSizeBytes() { final ApplicationInfo app = mContext.getApplicationInfo(); final String primaryUuid = getPrimaryStorageUuid(); if (Objects.equals(app.volumeUuid, primaryUuid)) { return -1; } try { return mStorageManager.getCacheSizeBytes(primaryUuid, app.uid); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } private static final String XATTR_ATOMIC = "user.atomic"; private static final String XATTR_TOMBSTONE = "user.tombstone"; /** {@hide} */ private static void setCacheBehavior(File path, String name, boolean enabled) throws IOException { if (!path.isDirectory()) { throw new IOException("Cache behavior can only be set on directories"); } if (enabled) { try { Os.setxattr(path.getAbsolutePath(), name, "1".getBytes(StandardCharsets.UTF_8), 0); } catch (ErrnoException e) { throw e.rethrowAsIOException(); } } else { try { Os.removexattr(path.getAbsolutePath(), name); } catch (ErrnoException e) { if (e.errno != OsConstants.ENODATA) { throw e.rethrowAsIOException(); } } } } /** {@hide} */ private static boolean isCacheBehavior(File path, String name) throws IOException { try { Os.getxattr(path.getAbsolutePath(), name); return true; } catch (ErrnoException e) { if (e.errno != OsConstants.ENODATA) { throw e.rethrowAsIOException(); } else { return false; } } } /** * Enable or disable special cache behavior that treats this directory and * its contents as an atomic unit. * <p> * When enabled and this directory is considered for automatic deletion by * the OS, all contained files will either be deleted together, or not at * all. This is useful when you have a directory that contains several * related metadata files that depend on each other, such as movie file and * a subtitle file. * <p> * When enabled, the <em>newest</em> {@link File#lastModified()} value of * any contained files is considered the modified time of the entire * directory. * <p> * This behavior can only be set on a directory, and it applies recursively * to all contained files and directories. */ public void setCacheBehaviorAtomic(File path, boolean atomic) throws IOException { setCacheBehavior(path, XATTR_ATOMIC, atomic); } /** * Read the current value set by * {@link #setCacheBehaviorAtomic(File, boolean)}. */ public boolean isCacheBehaviorAtomic(File path) throws IOException { return isCacheBehavior(path, XATTR_ATOMIC); } /** * Enable or disable special cache behavior that leaves deleted cache files * intact as tombstones. * <p> * When enabled and a file contained in this directory is automatically * deleted by the OS, the file will be truncated to have a length of 0 bytes * instead of being fully deleted. This is useful if you need to distinguish * between a file that was deleted versus one that never existed. * <p> * This behavior can only be set on a directory, and it applies recursively * to all contained files and directories. * <p class="note"> * Note: this behavior is ignored completely if the user explicitly requests * that all cached data be cleared. * </p> */ public void setCacheBehaviorTombstone(File path, boolean tombstone) throws IOException { setCacheBehavior(path, XATTR_TOMBSTONE, tombstone); } /** * Read the current value set by * {@link #setCacheBehaviorTombstone(File, boolean)}. */ public boolean isCacheBehaviorTombstone(File path) throws IOException { return isCacheBehavior(path, XATTR_TOMBSTONE); } private final Object mFuseAppLoopLock = new Object(); @GuardedBy("mFuseAppLoopLock") Loading