Loading api/test-current.txt +15 −0 Original line number Diff line number Diff line Loading @@ -12,6 +12,7 @@ package android { field public static final String CONFIGURE_DISPLAY_BRIGHTNESS = "android.permission.CONFIGURE_DISPLAY_BRIGHTNESS"; field public static final String FORCE_STOP_PACKAGES = "android.permission.FORCE_STOP_PACKAGES"; field public static final String MANAGE_ACTIVITY_STACKS = "android.permission.MANAGE_ACTIVITY_STACKS"; field public static final String MANAGE_CRATES = "android.permission.MANAGE_CRATES"; field public static final String MANAGE_ROLLBACKS = "android.permission.MANAGE_ROLLBACKS"; field public static final String READ_CELL_BROADCASTS = "android.permission.READ_CELL_BROADCASTS"; field public static final String REMOVE_TASKS = "android.permission.REMOVE_TASKS"; Loading Loading @@ -629,6 +630,9 @@ package android.app.usage { public class StorageStatsManager { method public boolean isQuotaSupported(@NonNull java.util.UUID); method public boolean isReservedSupported(@NonNull java.util.UUID); method @NonNull @WorkerThread public java.util.Collection<android.os.storage.CrateInfo> queryCratesForPackage(@NonNull java.util.UUID, @NonNull String, @NonNull android.os.UserHandle) throws java.io.IOException, android.content.pm.PackageManager.NameNotFoundException; method @NonNull @WorkerThread public java.util.Collection<android.os.storage.CrateInfo> queryCratesForUid(@NonNull java.util.UUID, int) throws java.io.IOException, android.content.pm.PackageManager.NameNotFoundException; method @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_CRATES) @WorkerThread public java.util.Collection<android.os.storage.CrateInfo> queryCratesForUser(@NonNull java.util.UUID, @NonNull android.os.UserHandle) throws java.io.IOException, android.content.pm.PackageManager.NameNotFoundException; } public final class UsageStatsManager { Loading Loading @@ -2314,6 +2318,17 @@ package android.os.image { package android.os.storage { public final class CrateInfo implements android.os.Parcelable { ctor public CrateInfo(@NonNull CharSequence, long); ctor public CrateInfo(@NonNull CharSequence); method @Nullable public static android.os.storage.CrateInfo copyFrom(int, @Nullable String, @Nullable String); method public int describeContents(); method public long getExpirationMillis(); method @NonNull public CharSequence getLabel(); method public void writeToParcel(@Nullable android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.os.storage.CrateInfo> CREATOR; } public class StorageManager { method public static boolean hasIsolatedStorage(); } Loading core/java/android/app/usage/IStorageStatsManager.aidl +8 −0 Original line number Diff line number Diff line Loading @@ -18,6 +18,8 @@ package android.app.usage; import android.app.usage.StorageStats; import android.app.usage.ExternalStorageStats; import android.content.pm.ParceledListSlice; import android.os.storage.CrateInfo; /** {@hide} */ interface IStorageStatsManager { Loading @@ -31,4 +33,10 @@ interface IStorageStatsManager { StorageStats queryStatsForUid(String volumeUuid, int uid, String callingPackage); StorageStats queryStatsForUser(String volumeUuid, int userId, String callingPackage); ExternalStorageStats queryExternalStatsForUser(String volumeUuid, int userId, String callingPackage); ParceledListSlice /* CrateInfo */ queryCratesForPackage(String volumeUuid, String packageName, int userId, String callingPackage); ParceledListSlice /* CrateInfo */ queryCratesForUid(String volumeUuid, int uid, String callingPackage); ParceledListSlice /* CrateInfo */ queryCratesForUser(String volumeUuid, int userId, String callingPackage); } core/java/android/app/usage/StorageStatsManager.java +101 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import static android.os.storage.StorageManager.convert; import android.annotation.BytesLong; import android.annotation.NonNull; import android.annotation.RequiresPermission; import android.annotation.SystemService; import android.annotation.TestApi; import android.annotation.WorkerThread; Loading @@ -27,15 +28,19 @@ import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.ParceledListSlice; import android.os.ParcelableException; import android.os.RemoteException; import android.os.UserHandle; import android.os.storage.CrateInfo; import android.os.storage.StorageManager; import com.android.internal.util.Preconditions; import java.io.File; import java.io.IOException; import java.util.Collection; import java.util.Objects; import java.util.UUID; /** Loading Loading @@ -347,4 +352,100 @@ public class StorageStatsManager { throw e.rethrowFromSystemServer(); } } /** * Return all of crate information for the specified storageUuid, packageName, and * userHandle. * * @param storageUuid the UUID of the storage volume you're interested in, * such as {@link StorageManager#UUID_DEFAULT}. * @param uid the uid you're interested in. * @return the collection of crate information. * @throws PackageManager.NameNotFoundException when the package name is not found. * @throws IOException cause by IO, not support, or the other reasons. * @hide */ @TestApi @WorkerThread @NonNull public Collection<CrateInfo> queryCratesForUid(@NonNull UUID storageUuid, int uid) throws IOException, PackageManager.NameNotFoundException { try { ParceledListSlice<CrateInfo> crateInfoList = mService.queryCratesForUid(convert(storageUuid), uid, mContext.getOpPackageName()); return Objects.requireNonNull(crateInfoList).getList(); } catch (ParcelableException e) { e.maybeRethrow(PackageManager.NameNotFoundException.class); e.maybeRethrow(IOException.class); throw new RuntimeException(e); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * Return all of crates information for the specified storageUuid, packageName, and * userHandle. * * @param storageUuid the UUID of the storage volume you're interested in, * such as {@link StorageManager#UUID_DEFAULT}. * @param packageName the package name you're interested in. * @param user the user you're interested in. * @return the collection of crate information. * @throws PackageManager.NameNotFoundException when the package name is not found. * @throws IOException cause by IO, not support, or the other reasons. * @hide */ @WorkerThread @TestApi @NonNull public Collection<CrateInfo> queryCratesForPackage(@NonNull UUID storageUuid, @NonNull String packageName, @NonNull UserHandle user) throws PackageManager.NameNotFoundException, IOException { try { ParceledListSlice<CrateInfo> crateInfoList = mService.queryCratesForPackage(convert(storageUuid), packageName, user.getIdentifier(), mContext.getOpPackageName()); return Objects.requireNonNull(crateInfoList).getList(); } catch (ParcelableException e) { e.maybeRethrow(PackageManager.NameNotFoundException.class); e.maybeRethrow(IOException.class); throw new RuntimeException(e); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * Return all of crate information for the specified storageUuid, packageName, and * userHandle. * * @param storageUuid the UUID of the storage volume you're interested in, * such as {@link StorageManager#UUID_DEFAULT}. * @param user the user you're interested in. * @return the collection of crate information. * @throws PackageManager.NameNotFoundException when the package name is not found. * @throws IOException cause by IO, not support, or the other reasons. * @hide */ @WorkerThread @TestApi @RequiresPermission(android.Manifest.permission.MANAGE_CRATES) @NonNull public Collection<CrateInfo> queryCratesForUser(@NonNull UUID storageUuid, @NonNull UserHandle user) throws PackageManager.NameNotFoundException, IOException { try { ParceledListSlice<CrateInfo> crateInfoList = mService.queryCratesForUser(convert(storageUuid), user.getIdentifier(), mContext.getOpPackageName()); return Objects.requireNonNull(crateInfoList).getList(); } catch (ParcelableException e) { e.maybeRethrow(PackageManager.NameNotFoundException.class); e.maybeRethrow(IOException.class); throw new RuntimeException(e); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } } core/java/android/os/storage/CrateInfo.aidl 0 → 100644 +21 −0 Original line number Diff line number Diff line /* * Copyright (C) 2019 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.os.storage; /** * @hide */ parcelable CrateInfo; core/java/android/os/storage/CrateInfo.java 0 → 100644 +282 −0 Original line number Diff line number Diff line /* * Copyright (C) 2019 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.os.storage; import android.annotation.CurrentTimeMillisLong; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.TestApi; import android.app.usage.StorageStatsManager; import android.content.Context; import android.os.Parcel; import android.os.Parcelable; import android.os.UserHandle; import android.text.TextUtils; import com.android.internal.util.Preconditions; import java.util.UUID; /** * The CrateInfo describe the crate information. * <p> * It describe the following items. * <ul> * <li>The crate id that is the name of the child directory in * {@link Context#getCrateDir(String)}</li> * <li>Label to provide human readable text for the users.</li> * <li>Expiration information. When the crate is expired and the run .</li> * * </ul>for the directory * </p> * @hide */ @TestApi public final class CrateInfo implements Parcelable { private static final String TAG = "CrateInfo"; /** * The following member fields whose value are set by apps and retrieved by system_server. */ private CharSequence mLabel; @CurrentTimeMillisLong private long mExpiration; /** * The following member fields whose value are retrieved by installd. * <p>{@link android.app.usage.StorageStatsManager#queryCratesForUser(UUID, UserHandle)} query * all of crates for the specified UserHandle. That means the return crate list whose elements * may have the same userId but different package name. Each crate needs the information to tell * the caller from where package comes. * </p> */ private int mUid; /** * The following member fields whose value are retrieved by installd. * <p>Both {@link StorageStatsManager#queryCratesForUid(UUID, int)} and * {@link android.app.usage.StorageStatsManager#queryCratesForUser(UUID, UserHandle)} query * all of crates for the specified uid or userId. That means the return crate list whose * elements may have the same uid or userId but different package name. Each crate needs the * information to tell the caller from where package comes. * </p> */ @Nullable private String mPackageName; /** * The following member fields whose value are retrieved by system_server. * <p> * The child directories in {@link Context#getCrateDir(String)} are crates. Each directories * is a crate. The folder name is the crate id. * </p><p> * Can't apply check if the path is validated or not because it need pass through the * parcel. * </p> */ @Nullable private String mId; private CrateInfo() { mExpiration = 0; } /** * To create the crateInfo by passing validated label. * @param label a display name for the crate * @param expiration It's positive integer. if current time is larger than the expiration, the * files under this crate will be considered to be deleted. Default value is 0. * @throws IllegalArgumentException cause IllegalArgumentException when label is null * or empty string */ public CrateInfo(@NonNull CharSequence label, @CurrentTimeMillisLong long expiration) { Preconditions.checkStringNotEmpty(label, "Label should not be either null or empty string"); Preconditions.checkArgumentNonnegative(expiration, "Expiration should be non negative number"); mLabel = label; mExpiration = expiration; } /** * To create the crateInfo by passing validated label. * @param label a display name for the crate * @throws IllegalArgumentException cause IllegalArgumentException when label is null * or empty string */ public CrateInfo(@NonNull CharSequence label) { this(label, 0); } /** * To get the meaningful text of the crate for the users. * @return the meaningful text */ @NonNull public CharSequence getLabel() { if (TextUtils.isEmpty(mLabel)) { return mId; } return mLabel; } /** * To return the expiration time. * <p> * If the current time is larger than expiration time, the crate files are considered to be * deleted. * </p> * @return the expiration time */ @CurrentTimeMillisLong public long getExpirationMillis() { return mExpiration; } /** * To set the expiration time. * @param expiration the expiration time * @hide */ public void setExpiration(@CurrentTimeMillisLong long expiration) { Preconditions.checkArgumentNonnegative(expiration); mExpiration = expiration; } @Override public int hashCode() { return super.hashCode(); } /** * To compare with crateinfo when selves' mId is validated. * <p>The validated crateinfo.mId must be validated the following items. * <ul> * <li>mId is not null</li> * <li>mId is not empty string</li> * </ul> * </p> * @param obj the reference object with which to compare. * @return true when selves's mId is validated and equal to crateinfo.mId. */ @Override public boolean equals(@Nullable Object obj) { if (obj == null) { return false; } if (obj instanceof CrateInfo) { CrateInfo crateInfo = (CrateInfo) obj; if (!TextUtils.isEmpty(mId) && TextUtils.equals(mId, crateInfo.mId)) { return true; } } return super.equals(obj); } @Override public int describeContents() { return 0; } @Override public void writeToParcel(@Nullable Parcel dest, int flags) { if (dest == null) { return; } dest.writeCharSequence(mLabel); dest.writeLong(mExpiration); dest.writeInt(mUid); dest.writeString(mPackageName); dest.writeString(mId); } /** * To read the data from parcel. * <p> * It's called by StorageStatsService. * </p> * @hide */ public void readFromParcel(@Nullable Parcel in) { if (in == null) { return; } mLabel = in.readCharSequence(); mExpiration = in.readLong(); mUid = in.readInt(); mPackageName = in.readString(); mId = in.readString(); } @NonNull public static final Creator<CrateInfo> CREATOR = new Creator<>() { @NonNull @Override public CrateInfo createFromParcel(@NonNull Parcel in) { CrateInfo crateInfo = new CrateInfo(); crateInfo.readFromParcel(in); return crateInfo; } @NonNull @Override public CrateInfo[] newArray(int size) { return new CrateInfo[size]; } }; /** * To copy the information from service into crateinfo. * <p> * This function is called in system_server. The copied information includes * <ul> * <li>uid</li> * <li>package name</li> * <li>crate id</li> * </ul> * </p> * @param uid the uid that the crate belong to * @param packageName the package name that the crate belong to * @param id the crate dir * @return the CrateInfo instance * @hide */ @TestApi @Nullable public static CrateInfo copyFrom(int uid, @Nullable String packageName, @Nullable String id) { if (!UserHandle.isApp(uid) || TextUtils.isEmpty(packageName) || TextUtils.isEmpty(id)) { return null; } CrateInfo crateInfo = new CrateInfo(id /* default label = id */, 0); crateInfo.mUid = uid; crateInfo.mPackageName = packageName; crateInfo.mId = id; return crateInfo; } } Loading
api/test-current.txt +15 −0 Original line number Diff line number Diff line Loading @@ -12,6 +12,7 @@ package android { field public static final String CONFIGURE_DISPLAY_BRIGHTNESS = "android.permission.CONFIGURE_DISPLAY_BRIGHTNESS"; field public static final String FORCE_STOP_PACKAGES = "android.permission.FORCE_STOP_PACKAGES"; field public static final String MANAGE_ACTIVITY_STACKS = "android.permission.MANAGE_ACTIVITY_STACKS"; field public static final String MANAGE_CRATES = "android.permission.MANAGE_CRATES"; field public static final String MANAGE_ROLLBACKS = "android.permission.MANAGE_ROLLBACKS"; field public static final String READ_CELL_BROADCASTS = "android.permission.READ_CELL_BROADCASTS"; field public static final String REMOVE_TASKS = "android.permission.REMOVE_TASKS"; Loading Loading @@ -629,6 +630,9 @@ package android.app.usage { public class StorageStatsManager { method public boolean isQuotaSupported(@NonNull java.util.UUID); method public boolean isReservedSupported(@NonNull java.util.UUID); method @NonNull @WorkerThread public java.util.Collection<android.os.storage.CrateInfo> queryCratesForPackage(@NonNull java.util.UUID, @NonNull String, @NonNull android.os.UserHandle) throws java.io.IOException, android.content.pm.PackageManager.NameNotFoundException; method @NonNull @WorkerThread public java.util.Collection<android.os.storage.CrateInfo> queryCratesForUid(@NonNull java.util.UUID, int) throws java.io.IOException, android.content.pm.PackageManager.NameNotFoundException; method @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_CRATES) @WorkerThread public java.util.Collection<android.os.storage.CrateInfo> queryCratesForUser(@NonNull java.util.UUID, @NonNull android.os.UserHandle) throws java.io.IOException, android.content.pm.PackageManager.NameNotFoundException; } public final class UsageStatsManager { Loading Loading @@ -2314,6 +2318,17 @@ package android.os.image { package android.os.storage { public final class CrateInfo implements android.os.Parcelable { ctor public CrateInfo(@NonNull CharSequence, long); ctor public CrateInfo(@NonNull CharSequence); method @Nullable public static android.os.storage.CrateInfo copyFrom(int, @Nullable String, @Nullable String); method public int describeContents(); method public long getExpirationMillis(); method @NonNull public CharSequence getLabel(); method public void writeToParcel(@Nullable android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.os.storage.CrateInfo> CREATOR; } public class StorageManager { method public static boolean hasIsolatedStorage(); } Loading
core/java/android/app/usage/IStorageStatsManager.aidl +8 −0 Original line number Diff line number Diff line Loading @@ -18,6 +18,8 @@ package android.app.usage; import android.app.usage.StorageStats; import android.app.usage.ExternalStorageStats; import android.content.pm.ParceledListSlice; import android.os.storage.CrateInfo; /** {@hide} */ interface IStorageStatsManager { Loading @@ -31,4 +33,10 @@ interface IStorageStatsManager { StorageStats queryStatsForUid(String volumeUuid, int uid, String callingPackage); StorageStats queryStatsForUser(String volumeUuid, int userId, String callingPackage); ExternalStorageStats queryExternalStatsForUser(String volumeUuid, int userId, String callingPackage); ParceledListSlice /* CrateInfo */ queryCratesForPackage(String volumeUuid, String packageName, int userId, String callingPackage); ParceledListSlice /* CrateInfo */ queryCratesForUid(String volumeUuid, int uid, String callingPackage); ParceledListSlice /* CrateInfo */ queryCratesForUser(String volumeUuid, int userId, String callingPackage); }
core/java/android/app/usage/StorageStatsManager.java +101 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import static android.os.storage.StorageManager.convert; import android.annotation.BytesLong; import android.annotation.NonNull; import android.annotation.RequiresPermission; import android.annotation.SystemService; import android.annotation.TestApi; import android.annotation.WorkerThread; Loading @@ -27,15 +28,19 @@ import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.ParceledListSlice; import android.os.ParcelableException; import android.os.RemoteException; import android.os.UserHandle; import android.os.storage.CrateInfo; import android.os.storage.StorageManager; import com.android.internal.util.Preconditions; import java.io.File; import java.io.IOException; import java.util.Collection; import java.util.Objects; import java.util.UUID; /** Loading Loading @@ -347,4 +352,100 @@ public class StorageStatsManager { throw e.rethrowFromSystemServer(); } } /** * Return all of crate information for the specified storageUuid, packageName, and * userHandle. * * @param storageUuid the UUID of the storage volume you're interested in, * such as {@link StorageManager#UUID_DEFAULT}. * @param uid the uid you're interested in. * @return the collection of crate information. * @throws PackageManager.NameNotFoundException when the package name is not found. * @throws IOException cause by IO, not support, or the other reasons. * @hide */ @TestApi @WorkerThread @NonNull public Collection<CrateInfo> queryCratesForUid(@NonNull UUID storageUuid, int uid) throws IOException, PackageManager.NameNotFoundException { try { ParceledListSlice<CrateInfo> crateInfoList = mService.queryCratesForUid(convert(storageUuid), uid, mContext.getOpPackageName()); return Objects.requireNonNull(crateInfoList).getList(); } catch (ParcelableException e) { e.maybeRethrow(PackageManager.NameNotFoundException.class); e.maybeRethrow(IOException.class); throw new RuntimeException(e); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * Return all of crates information for the specified storageUuid, packageName, and * userHandle. * * @param storageUuid the UUID of the storage volume you're interested in, * such as {@link StorageManager#UUID_DEFAULT}. * @param packageName the package name you're interested in. * @param user the user you're interested in. * @return the collection of crate information. * @throws PackageManager.NameNotFoundException when the package name is not found. * @throws IOException cause by IO, not support, or the other reasons. * @hide */ @WorkerThread @TestApi @NonNull public Collection<CrateInfo> queryCratesForPackage(@NonNull UUID storageUuid, @NonNull String packageName, @NonNull UserHandle user) throws PackageManager.NameNotFoundException, IOException { try { ParceledListSlice<CrateInfo> crateInfoList = mService.queryCratesForPackage(convert(storageUuid), packageName, user.getIdentifier(), mContext.getOpPackageName()); return Objects.requireNonNull(crateInfoList).getList(); } catch (ParcelableException e) { e.maybeRethrow(PackageManager.NameNotFoundException.class); e.maybeRethrow(IOException.class); throw new RuntimeException(e); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * Return all of crate information for the specified storageUuid, packageName, and * userHandle. * * @param storageUuid the UUID of the storage volume you're interested in, * such as {@link StorageManager#UUID_DEFAULT}. * @param user the user you're interested in. * @return the collection of crate information. * @throws PackageManager.NameNotFoundException when the package name is not found. * @throws IOException cause by IO, not support, or the other reasons. * @hide */ @WorkerThread @TestApi @RequiresPermission(android.Manifest.permission.MANAGE_CRATES) @NonNull public Collection<CrateInfo> queryCratesForUser(@NonNull UUID storageUuid, @NonNull UserHandle user) throws PackageManager.NameNotFoundException, IOException { try { ParceledListSlice<CrateInfo> crateInfoList = mService.queryCratesForUser(convert(storageUuid), user.getIdentifier(), mContext.getOpPackageName()); return Objects.requireNonNull(crateInfoList).getList(); } catch (ParcelableException e) { e.maybeRethrow(PackageManager.NameNotFoundException.class); e.maybeRethrow(IOException.class); throw new RuntimeException(e); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } }
core/java/android/os/storage/CrateInfo.aidl 0 → 100644 +21 −0 Original line number Diff line number Diff line /* * Copyright (C) 2019 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.os.storage; /** * @hide */ parcelable CrateInfo;
core/java/android/os/storage/CrateInfo.java 0 → 100644 +282 −0 Original line number Diff line number Diff line /* * Copyright (C) 2019 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.os.storage; import android.annotation.CurrentTimeMillisLong; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.TestApi; import android.app.usage.StorageStatsManager; import android.content.Context; import android.os.Parcel; import android.os.Parcelable; import android.os.UserHandle; import android.text.TextUtils; import com.android.internal.util.Preconditions; import java.util.UUID; /** * The CrateInfo describe the crate information. * <p> * It describe the following items. * <ul> * <li>The crate id that is the name of the child directory in * {@link Context#getCrateDir(String)}</li> * <li>Label to provide human readable text for the users.</li> * <li>Expiration information. When the crate is expired and the run .</li> * * </ul>for the directory * </p> * @hide */ @TestApi public final class CrateInfo implements Parcelable { private static final String TAG = "CrateInfo"; /** * The following member fields whose value are set by apps and retrieved by system_server. */ private CharSequence mLabel; @CurrentTimeMillisLong private long mExpiration; /** * The following member fields whose value are retrieved by installd. * <p>{@link android.app.usage.StorageStatsManager#queryCratesForUser(UUID, UserHandle)} query * all of crates for the specified UserHandle. That means the return crate list whose elements * may have the same userId but different package name. Each crate needs the information to tell * the caller from where package comes. * </p> */ private int mUid; /** * The following member fields whose value are retrieved by installd. * <p>Both {@link StorageStatsManager#queryCratesForUid(UUID, int)} and * {@link android.app.usage.StorageStatsManager#queryCratesForUser(UUID, UserHandle)} query * all of crates for the specified uid or userId. That means the return crate list whose * elements may have the same uid or userId but different package name. Each crate needs the * information to tell the caller from where package comes. * </p> */ @Nullable private String mPackageName; /** * The following member fields whose value are retrieved by system_server. * <p> * The child directories in {@link Context#getCrateDir(String)} are crates. Each directories * is a crate. The folder name is the crate id. * </p><p> * Can't apply check if the path is validated or not because it need pass through the * parcel. * </p> */ @Nullable private String mId; private CrateInfo() { mExpiration = 0; } /** * To create the crateInfo by passing validated label. * @param label a display name for the crate * @param expiration It's positive integer. if current time is larger than the expiration, the * files under this crate will be considered to be deleted. Default value is 0. * @throws IllegalArgumentException cause IllegalArgumentException when label is null * or empty string */ public CrateInfo(@NonNull CharSequence label, @CurrentTimeMillisLong long expiration) { Preconditions.checkStringNotEmpty(label, "Label should not be either null or empty string"); Preconditions.checkArgumentNonnegative(expiration, "Expiration should be non negative number"); mLabel = label; mExpiration = expiration; } /** * To create the crateInfo by passing validated label. * @param label a display name for the crate * @throws IllegalArgumentException cause IllegalArgumentException when label is null * or empty string */ public CrateInfo(@NonNull CharSequence label) { this(label, 0); } /** * To get the meaningful text of the crate for the users. * @return the meaningful text */ @NonNull public CharSequence getLabel() { if (TextUtils.isEmpty(mLabel)) { return mId; } return mLabel; } /** * To return the expiration time. * <p> * If the current time is larger than expiration time, the crate files are considered to be * deleted. * </p> * @return the expiration time */ @CurrentTimeMillisLong public long getExpirationMillis() { return mExpiration; } /** * To set the expiration time. * @param expiration the expiration time * @hide */ public void setExpiration(@CurrentTimeMillisLong long expiration) { Preconditions.checkArgumentNonnegative(expiration); mExpiration = expiration; } @Override public int hashCode() { return super.hashCode(); } /** * To compare with crateinfo when selves' mId is validated. * <p>The validated crateinfo.mId must be validated the following items. * <ul> * <li>mId is not null</li> * <li>mId is not empty string</li> * </ul> * </p> * @param obj the reference object with which to compare. * @return true when selves's mId is validated and equal to crateinfo.mId. */ @Override public boolean equals(@Nullable Object obj) { if (obj == null) { return false; } if (obj instanceof CrateInfo) { CrateInfo crateInfo = (CrateInfo) obj; if (!TextUtils.isEmpty(mId) && TextUtils.equals(mId, crateInfo.mId)) { return true; } } return super.equals(obj); } @Override public int describeContents() { return 0; } @Override public void writeToParcel(@Nullable Parcel dest, int flags) { if (dest == null) { return; } dest.writeCharSequence(mLabel); dest.writeLong(mExpiration); dest.writeInt(mUid); dest.writeString(mPackageName); dest.writeString(mId); } /** * To read the data from parcel. * <p> * It's called by StorageStatsService. * </p> * @hide */ public void readFromParcel(@Nullable Parcel in) { if (in == null) { return; } mLabel = in.readCharSequence(); mExpiration = in.readLong(); mUid = in.readInt(); mPackageName = in.readString(); mId = in.readString(); } @NonNull public static final Creator<CrateInfo> CREATOR = new Creator<>() { @NonNull @Override public CrateInfo createFromParcel(@NonNull Parcel in) { CrateInfo crateInfo = new CrateInfo(); crateInfo.readFromParcel(in); return crateInfo; } @NonNull @Override public CrateInfo[] newArray(int size) { return new CrateInfo[size]; } }; /** * To copy the information from service into crateinfo. * <p> * This function is called in system_server. The copied information includes * <ul> * <li>uid</li> * <li>package name</li> * <li>crate id</li> * </ul> * </p> * @param uid the uid that the crate belong to * @param packageName the package name that the crate belong to * @param id the crate dir * @return the CrateInfo instance * @hide */ @TestApi @Nullable public static CrateInfo copyFrom(int uid, @Nullable String packageName, @Nullable String id) { if (!UserHandle.isApp(uid) || TextUtils.isEmpty(packageName) || TextUtils.isEmpty(id)) { return null; } CrateInfo crateInfo = new CrateInfo(id /* default label = id */, 0); crateInfo.mUid = uid; crateInfo.mPackageName = packageName; crateInfo.mId = id; return crateInfo; } }