Loading apex/blobstore/framework/java/android/app/blob/BlobStoreManager.java +9 −0 Original line number Diff line number Diff line Loading @@ -145,6 +145,9 @@ public class BlobStoreManager { /** @hide */ public static final int INVALID_RES_ID = -1; /** @hide */ public static final String DESC_RES_TYPE_STRING = "string"; private final Context mContext; private final IBlobStoreManager mService; Loading Loading @@ -269,6 +272,9 @@ public class BlobStoreManager { * <p> When an app acquires a lease on a blob, the System will try to keep this * blob around but note that it can still be deleted if it was requested by the user. * * <p> In case the resource name for the {@code descriptionResId} is modified as part of * an app update, apps should re-acquire the lease with the new resource id. * * @param blobHandle the {@link BlobHandle} representing the blob that the caller wants to * acquire a lease for. * @param descriptionResId the resource id for a short description string that can be surfaced Loading Loading @@ -380,6 +386,9 @@ public class BlobStoreManager { * <p> When an app acquires a lease on a blob, the System will try to keep this * blob around but note that it can still be deleted if it was requested by the user. * * <p> In case the resource name for the {@code descriptionResId} is modified as part of * an app update, apps should re-acquire the lease with the new resource id. * * @param blobHandle the {@link BlobHandle} representing the blob that the caller wants to * acquire a lease for. * @param descriptionResId the resource id for a short description string that can be surfaced Loading apex/blobstore/framework/java/android/app/blob/XmlTags.java +1 −1 Original line number Diff line number Diff line Loading @@ -51,6 +51,6 @@ public final class XmlTags { // For leasee public static final String TAG_LEASEE = "l"; public static final String ATTR_DESCRIPTION_RES_ID = "rid"; public static final String ATTR_DESCRIPTION_RES_NAME = "rn"; public static final String ATTR_DESCRIPTION = "d"; } apex/blobstore/service/java/com/android/server/blob/BlobMetadata.java +94 −26 Original line number Diff line number Diff line Loading @@ -15,8 +15,9 @@ */ package com.android.server.blob; import static android.app.blob.BlobStoreManager.DESC_RES_TYPE_STRING; import static android.app.blob.XmlTags.ATTR_DESCRIPTION; import static android.app.blob.XmlTags.ATTR_DESCRIPTION_RES_ID; import static android.app.blob.XmlTags.ATTR_DESCRIPTION_RES_NAME; import static android.app.blob.XmlTags.ATTR_EXPIRY_TIME; import static android.app.blob.XmlTags.ATTR_ID; import static android.app.blob.XmlTags.ATTR_PACKAGE; Loading @@ -29,7 +30,9 @@ import static android.app.blob.XmlTags.TAG_LEASEE; import static android.os.Process.INVALID_UID; import static android.system.OsConstants.O_RDONLY; import static com.android.server.blob.BlobStoreConfig.LOGV; import static com.android.server.blob.BlobStoreConfig.TAG; import static com.android.server.blob.BlobStoreConfig.XML_VERSION_ADD_DESC_RES_NAME; import static com.android.server.blob.BlobStoreConfig.XML_VERSION_ADD_STRING_DESC; import android.annotation.NonNull; Loading Loading @@ -154,7 +157,7 @@ class BlobMetadata { synchronized (mMetadataLock) { // We need to override the leasee data, so first remove any existing // leasee before adding the new one. final Leasee leasee = new Leasee(callingPackage, callingUid, final Leasee leasee = new Leasee(mContext, callingPackage, callingUid, descriptionResId, description, leaseExpiryTimeMillis); mLeasees.remove(leasee); mLeasees.add(leasee); Loading Loading @@ -459,59 +462,123 @@ class BlobMetadata { } static final class Leasee extends Accessor { public final int descriptionResId; public final String descriptionResEntryName; public final CharSequence description; public final long expiryTimeMillis; Leasee(String packageName, int uid, int descriptionResId, CharSequence description, long expiryTimeMillis) { Leasee(@NonNull Context context, @NonNull String packageName, int uid, int descriptionResId, @Nullable CharSequence description, long expiryTimeMillis) { super(packageName, uid); this.descriptionResId = descriptionResId; final Resources packageResources = getPackageResources(context, packageName, UserHandle.getUserId(uid)); this.descriptionResEntryName = getResourceEntryName(packageResources, descriptionResId); this.expiryTimeMillis = expiryTimeMillis; this.description = description == null ? getDescription(packageResources, descriptionResId) : description; } Leasee(String packageName, int uid, @Nullable String descriptionResEntryName, @Nullable CharSequence description, long expiryTimeMillis) { super(packageName, uid); this.descriptionResEntryName = descriptionResEntryName; this.expiryTimeMillis = expiryTimeMillis; this.description = description; } @Nullable private static String getResourceEntryName(@Nullable Resources packageResources, int resId) { if (!ResourceId.isValid(resId) || packageResources == null) { return null; } return packageResources.getResourceEntryName(resId); } @Nullable private static String getDescription(@NonNull Context context, @NonNull String descriptionResEntryName, @NonNull String packageName, int userId) { if (descriptionResEntryName == null || descriptionResEntryName.isEmpty()) { return null; } final Resources resources = getPackageResources(context, packageName, userId); if (resources == null) { return null; } try { final int resId = resources.getIdentifier(descriptionResEntryName, DESC_RES_TYPE_STRING, packageName); return resId <= 0 ? null : resources.getString(resId); } catch (Resources.NotFoundException e) { if (LOGV) { Slog.w(TAG, "Description resource not found", e); } return null; } } @Nullable private static String getDescription(@Nullable Resources packageResources, int descriptionResId) { if (!ResourceId.isValid(descriptionResId) || packageResources == null) { return null; } return packageResources.getString(descriptionResId); } boolean isStillValid() { return expiryTimeMillis == 0 || expiryTimeMillis <= System.currentTimeMillis(); } void dump(Context context, IndentingPrintWriter fout) { void dump(@NonNull Context context, @NonNull IndentingPrintWriter fout) { fout.println("desc: " + getDescriptionToDump(context)); fout.println("expiryMs: " + expiryTimeMillis); } private String getDescriptionToDump(Context context) { String desc = null; if (ResourceId.isValid(descriptionResId)) { @NonNull private String getDescriptionToDump(@NonNull Context context) { String desc = getDescription(context, descriptionResEntryName, packageName, UserHandle.getUserId(uid)); if (desc == null) { desc = description.toString(); } return desc == null ? "<none>" : desc; } @Nullable private static Resources getPackageResources(@NonNull Context context, @NonNull String packageName, int userId) { try { final Resources leaseeRes = context.getPackageManager() .getResourcesForApplicationAsUser( packageName, UserHandle.getUserId(uid)); desc = leaseeRes.getString(descriptionResId); return context.getPackageManager() .getResourcesForApplicationAsUser(packageName, userId); } catch (PackageManager.NameNotFoundException e) { Slog.d(TAG, "Unknown package in user " + UserHandle.getUserId(uid) + ": " Slog.d(TAG, "Unknown package in user " + userId + ": " + packageName, e); desc = "<none>"; } } else { desc = description.toString(); return null; } return desc; } void writeToXml(@NonNull XmlSerializer out) throws IOException { XmlUtils.writeStringAttribute(out, ATTR_PACKAGE, packageName); XmlUtils.writeIntAttribute(out, ATTR_UID, uid); XmlUtils.writeIntAttribute(out, ATTR_DESCRIPTION_RES_ID, descriptionResId); XmlUtils.writeStringAttribute(out, ATTR_DESCRIPTION_RES_NAME, descriptionResEntryName); XmlUtils.writeLongAttribute(out, ATTR_EXPIRY_TIME, expiryTimeMillis); XmlUtils.writeStringAttribute(out, ATTR_DESCRIPTION, description); } @NonNull static Leasee createFromXml(@NonNull XmlPullParser in, int version) throws IOException { static Leasee createFromXml(@NonNull XmlPullParser in, int version) throws IOException { final String packageName = XmlUtils.readStringAttribute(in, ATTR_PACKAGE); final int uid = XmlUtils.readIntAttribute(in, ATTR_UID); final int descriptionResId = XmlUtils.readIntAttribute(in, ATTR_DESCRIPTION_RES_ID); final String descriptionResEntryName; if (version >= XML_VERSION_ADD_DESC_RES_NAME) { descriptionResEntryName = XmlUtils.readStringAttribute( in, ATTR_DESCRIPTION_RES_NAME); } else { descriptionResEntryName = null; } final long expiryTimeMillis = XmlUtils.readLongAttribute(in, ATTR_EXPIRY_TIME); final CharSequence description; if (version >= XML_VERSION_ADD_STRING_DESC) { Loading @@ -520,7 +587,8 @@ class BlobMetadata { description = null; } return new Leasee(packageName, uid, descriptionResId, description, expiryTimeMillis); return new Leasee(packageName, uid, descriptionResEntryName, description, expiryTimeMillis); } } Loading apex/blobstore/service/java/com/android/server/blob/BlobStoreConfig.java +2 −1 Original line number Diff line number Diff line Loading @@ -32,8 +32,9 @@ class BlobStoreConfig { public static final int XML_VERSION_INIT = 1; // Added a string variant of lease description. public static final int XML_VERSION_ADD_STRING_DESC = 2; public static final int XML_VERSION_ADD_DESC_RES_NAME = 3; public static final int XML_VERSION_CURRENT = XML_VERSION_ADD_STRING_DESC; public static final int XML_VERSION_CURRENT = XML_VERSION_ADD_DESC_RES_NAME; private static final String ROOT_DIR_NAME = "blobstore"; private static final String BLOBS_DIR_NAME = "blobs"; Loading apex/blobstore/service/java/com/android/server/blob/BlobStoreManagerService.java +7 −2 Original line number Diff line number Diff line Loading @@ -54,6 +54,7 @@ import android.content.pm.ApplicationInfo; import android.content.pm.PackageManagerInternal; import android.content.pm.PackageStats; import android.content.res.ResourceId; import android.content.res.Resources; import android.os.Binder; import android.os.Handler; import android.os.HandlerThread; Loading Loading @@ -1187,8 +1188,12 @@ public class BlobStoreManagerService extends SystemService { final int callingUid = Binder.getCallingUid(); verifyCallingPackage(callingUid, packageName); acquireLeaseInternal(blobHandle, descriptionResId, description, leaseExpiryTimeMillis, callingUid, packageName); try { acquireLeaseInternal(blobHandle, descriptionResId, description, leaseExpiryTimeMillis, callingUid, packageName); } catch (Resources.NotFoundException e) { throw new IllegalArgumentException(e); } } @Override Loading Loading
apex/blobstore/framework/java/android/app/blob/BlobStoreManager.java +9 −0 Original line number Diff line number Diff line Loading @@ -145,6 +145,9 @@ public class BlobStoreManager { /** @hide */ public static final int INVALID_RES_ID = -1; /** @hide */ public static final String DESC_RES_TYPE_STRING = "string"; private final Context mContext; private final IBlobStoreManager mService; Loading Loading @@ -269,6 +272,9 @@ public class BlobStoreManager { * <p> When an app acquires a lease on a blob, the System will try to keep this * blob around but note that it can still be deleted if it was requested by the user. * * <p> In case the resource name for the {@code descriptionResId} is modified as part of * an app update, apps should re-acquire the lease with the new resource id. * * @param blobHandle the {@link BlobHandle} representing the blob that the caller wants to * acquire a lease for. * @param descriptionResId the resource id for a short description string that can be surfaced Loading Loading @@ -380,6 +386,9 @@ public class BlobStoreManager { * <p> When an app acquires a lease on a blob, the System will try to keep this * blob around but note that it can still be deleted if it was requested by the user. * * <p> In case the resource name for the {@code descriptionResId} is modified as part of * an app update, apps should re-acquire the lease with the new resource id. * * @param blobHandle the {@link BlobHandle} representing the blob that the caller wants to * acquire a lease for. * @param descriptionResId the resource id for a short description string that can be surfaced Loading
apex/blobstore/framework/java/android/app/blob/XmlTags.java +1 −1 Original line number Diff line number Diff line Loading @@ -51,6 +51,6 @@ public final class XmlTags { // For leasee public static final String TAG_LEASEE = "l"; public static final String ATTR_DESCRIPTION_RES_ID = "rid"; public static final String ATTR_DESCRIPTION_RES_NAME = "rn"; public static final String ATTR_DESCRIPTION = "d"; }
apex/blobstore/service/java/com/android/server/blob/BlobMetadata.java +94 −26 Original line number Diff line number Diff line Loading @@ -15,8 +15,9 @@ */ package com.android.server.blob; import static android.app.blob.BlobStoreManager.DESC_RES_TYPE_STRING; import static android.app.blob.XmlTags.ATTR_DESCRIPTION; import static android.app.blob.XmlTags.ATTR_DESCRIPTION_RES_ID; import static android.app.blob.XmlTags.ATTR_DESCRIPTION_RES_NAME; import static android.app.blob.XmlTags.ATTR_EXPIRY_TIME; import static android.app.blob.XmlTags.ATTR_ID; import static android.app.blob.XmlTags.ATTR_PACKAGE; Loading @@ -29,7 +30,9 @@ import static android.app.blob.XmlTags.TAG_LEASEE; import static android.os.Process.INVALID_UID; import static android.system.OsConstants.O_RDONLY; import static com.android.server.blob.BlobStoreConfig.LOGV; import static com.android.server.blob.BlobStoreConfig.TAG; import static com.android.server.blob.BlobStoreConfig.XML_VERSION_ADD_DESC_RES_NAME; import static com.android.server.blob.BlobStoreConfig.XML_VERSION_ADD_STRING_DESC; import android.annotation.NonNull; Loading Loading @@ -154,7 +157,7 @@ class BlobMetadata { synchronized (mMetadataLock) { // We need to override the leasee data, so first remove any existing // leasee before adding the new one. final Leasee leasee = new Leasee(callingPackage, callingUid, final Leasee leasee = new Leasee(mContext, callingPackage, callingUid, descriptionResId, description, leaseExpiryTimeMillis); mLeasees.remove(leasee); mLeasees.add(leasee); Loading Loading @@ -459,59 +462,123 @@ class BlobMetadata { } static final class Leasee extends Accessor { public final int descriptionResId; public final String descriptionResEntryName; public final CharSequence description; public final long expiryTimeMillis; Leasee(String packageName, int uid, int descriptionResId, CharSequence description, long expiryTimeMillis) { Leasee(@NonNull Context context, @NonNull String packageName, int uid, int descriptionResId, @Nullable CharSequence description, long expiryTimeMillis) { super(packageName, uid); this.descriptionResId = descriptionResId; final Resources packageResources = getPackageResources(context, packageName, UserHandle.getUserId(uid)); this.descriptionResEntryName = getResourceEntryName(packageResources, descriptionResId); this.expiryTimeMillis = expiryTimeMillis; this.description = description == null ? getDescription(packageResources, descriptionResId) : description; } Leasee(String packageName, int uid, @Nullable String descriptionResEntryName, @Nullable CharSequence description, long expiryTimeMillis) { super(packageName, uid); this.descriptionResEntryName = descriptionResEntryName; this.expiryTimeMillis = expiryTimeMillis; this.description = description; } @Nullable private static String getResourceEntryName(@Nullable Resources packageResources, int resId) { if (!ResourceId.isValid(resId) || packageResources == null) { return null; } return packageResources.getResourceEntryName(resId); } @Nullable private static String getDescription(@NonNull Context context, @NonNull String descriptionResEntryName, @NonNull String packageName, int userId) { if (descriptionResEntryName == null || descriptionResEntryName.isEmpty()) { return null; } final Resources resources = getPackageResources(context, packageName, userId); if (resources == null) { return null; } try { final int resId = resources.getIdentifier(descriptionResEntryName, DESC_RES_TYPE_STRING, packageName); return resId <= 0 ? null : resources.getString(resId); } catch (Resources.NotFoundException e) { if (LOGV) { Slog.w(TAG, "Description resource not found", e); } return null; } } @Nullable private static String getDescription(@Nullable Resources packageResources, int descriptionResId) { if (!ResourceId.isValid(descriptionResId) || packageResources == null) { return null; } return packageResources.getString(descriptionResId); } boolean isStillValid() { return expiryTimeMillis == 0 || expiryTimeMillis <= System.currentTimeMillis(); } void dump(Context context, IndentingPrintWriter fout) { void dump(@NonNull Context context, @NonNull IndentingPrintWriter fout) { fout.println("desc: " + getDescriptionToDump(context)); fout.println("expiryMs: " + expiryTimeMillis); } private String getDescriptionToDump(Context context) { String desc = null; if (ResourceId.isValid(descriptionResId)) { @NonNull private String getDescriptionToDump(@NonNull Context context) { String desc = getDescription(context, descriptionResEntryName, packageName, UserHandle.getUserId(uid)); if (desc == null) { desc = description.toString(); } return desc == null ? "<none>" : desc; } @Nullable private static Resources getPackageResources(@NonNull Context context, @NonNull String packageName, int userId) { try { final Resources leaseeRes = context.getPackageManager() .getResourcesForApplicationAsUser( packageName, UserHandle.getUserId(uid)); desc = leaseeRes.getString(descriptionResId); return context.getPackageManager() .getResourcesForApplicationAsUser(packageName, userId); } catch (PackageManager.NameNotFoundException e) { Slog.d(TAG, "Unknown package in user " + UserHandle.getUserId(uid) + ": " Slog.d(TAG, "Unknown package in user " + userId + ": " + packageName, e); desc = "<none>"; } } else { desc = description.toString(); return null; } return desc; } void writeToXml(@NonNull XmlSerializer out) throws IOException { XmlUtils.writeStringAttribute(out, ATTR_PACKAGE, packageName); XmlUtils.writeIntAttribute(out, ATTR_UID, uid); XmlUtils.writeIntAttribute(out, ATTR_DESCRIPTION_RES_ID, descriptionResId); XmlUtils.writeStringAttribute(out, ATTR_DESCRIPTION_RES_NAME, descriptionResEntryName); XmlUtils.writeLongAttribute(out, ATTR_EXPIRY_TIME, expiryTimeMillis); XmlUtils.writeStringAttribute(out, ATTR_DESCRIPTION, description); } @NonNull static Leasee createFromXml(@NonNull XmlPullParser in, int version) throws IOException { static Leasee createFromXml(@NonNull XmlPullParser in, int version) throws IOException { final String packageName = XmlUtils.readStringAttribute(in, ATTR_PACKAGE); final int uid = XmlUtils.readIntAttribute(in, ATTR_UID); final int descriptionResId = XmlUtils.readIntAttribute(in, ATTR_DESCRIPTION_RES_ID); final String descriptionResEntryName; if (version >= XML_VERSION_ADD_DESC_RES_NAME) { descriptionResEntryName = XmlUtils.readStringAttribute( in, ATTR_DESCRIPTION_RES_NAME); } else { descriptionResEntryName = null; } final long expiryTimeMillis = XmlUtils.readLongAttribute(in, ATTR_EXPIRY_TIME); final CharSequence description; if (version >= XML_VERSION_ADD_STRING_DESC) { Loading @@ -520,7 +587,8 @@ class BlobMetadata { description = null; } return new Leasee(packageName, uid, descriptionResId, description, expiryTimeMillis); return new Leasee(packageName, uid, descriptionResEntryName, description, expiryTimeMillis); } } Loading
apex/blobstore/service/java/com/android/server/blob/BlobStoreConfig.java +2 −1 Original line number Diff line number Diff line Loading @@ -32,8 +32,9 @@ class BlobStoreConfig { public static final int XML_VERSION_INIT = 1; // Added a string variant of lease description. public static final int XML_VERSION_ADD_STRING_DESC = 2; public static final int XML_VERSION_ADD_DESC_RES_NAME = 3; public static final int XML_VERSION_CURRENT = XML_VERSION_ADD_STRING_DESC; public static final int XML_VERSION_CURRENT = XML_VERSION_ADD_DESC_RES_NAME; private static final String ROOT_DIR_NAME = "blobstore"; private static final String BLOBS_DIR_NAME = "blobs"; Loading
apex/blobstore/service/java/com/android/server/blob/BlobStoreManagerService.java +7 −2 Original line number Diff line number Diff line Loading @@ -54,6 +54,7 @@ import android.content.pm.ApplicationInfo; import android.content.pm.PackageManagerInternal; import android.content.pm.PackageStats; import android.content.res.ResourceId; import android.content.res.Resources; import android.os.Binder; import android.os.Handler; import android.os.HandlerThread; Loading Loading @@ -1187,8 +1188,12 @@ public class BlobStoreManagerService extends SystemService { final int callingUid = Binder.getCallingUid(); verifyCallingPackage(callingUid, packageName); acquireLeaseInternal(blobHandle, descriptionResId, description, leaseExpiryTimeMillis, callingUid, packageName); try { acquireLeaseInternal(blobHandle, descriptionResId, description, leaseExpiryTimeMillis, callingUid, packageName); } catch (Resources.NotFoundException e) { throw new IllegalArgumentException(e); } } @Override Loading