diff options
5 files changed, 113 insertions, 30 deletions
diff --git a/apex/blobstore/framework/java/android/app/blob/BlobStoreManager.java b/apex/blobstore/framework/java/android/app/blob/BlobStoreManager.java index f53f1f19aea7..d1e28e99b6d6 100644 --- a/apex/blobstore/framework/java/android/app/blob/BlobStoreManager.java +++ b/apex/blobstore/framework/java/android/app/blob/BlobStoreManager.java @@ -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; @@ -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 @@ -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 diff --git a/apex/blobstore/framework/java/android/app/blob/XmlTags.java b/apex/blobstore/framework/java/android/app/blob/XmlTags.java index 9834d7477838..e64edc393769 100644 --- a/apex/blobstore/framework/java/android/app/blob/XmlTags.java +++ b/apex/blobstore/framework/java/android/app/blob/XmlTags.java @@ -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"; } diff --git a/apex/blobstore/service/java/com/android/server/blob/BlobMetadata.java b/apex/blobstore/service/java/com/android/server/blob/BlobMetadata.java index 4a85a69b82d3..888c3af8bbf7 100644 --- a/apex/blobstore/service/java/com/android/server/blob/BlobMetadata.java +++ b/apex/blobstore/service/java/com/android/server/blob/BlobMetadata.java @@ -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; @@ -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; @@ -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); @@ -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)) { - try { - final Resources leaseeRes = context.getPackageManager() - .getResourcesForApplicationAsUser( - packageName, UserHandle.getUserId(uid)); - desc = leaseeRes.getString(descriptionResId); - } catch (PackageManager.NameNotFoundException e) { - Slog.d(TAG, "Unknown package in user " + UserHandle.getUserId(uid) + ": " - + packageName, e); - desc = "<none>"; - } - } else { + @NonNull + private String getDescriptionToDump(@NonNull Context context) { + String desc = getDescription(context, descriptionResEntryName, packageName, + UserHandle.getUserId(uid)); + if (desc == null) { desc = description.toString(); } - return desc; + return desc == null ? "<none>" : desc; + } + + @Nullable + private static Resources getPackageResources(@NonNull Context context, + @NonNull String packageName, int userId) { + try { + return context.getPackageManager() + .getResourcesForApplicationAsUser(packageName, userId); + } catch (PackageManager.NameNotFoundException e) { + Slog.d(TAG, "Unknown package in user " + userId + ": " + + packageName, e); + return null; + } } 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) { @@ -520,7 +587,8 @@ class BlobMetadata { description = null; } - return new Leasee(packageName, uid, descriptionResId, description, expiryTimeMillis); + return new Leasee(packageName, uid, descriptionResEntryName, + description, expiryTimeMillis); } } diff --git a/apex/blobstore/service/java/com/android/server/blob/BlobStoreConfig.java b/apex/blobstore/service/java/com/android/server/blob/BlobStoreConfig.java index bcc1610435d9..6d31b2c30067 100644 --- a/apex/blobstore/service/java/com/android/server/blob/BlobStoreConfig.java +++ b/apex/blobstore/service/java/com/android/server/blob/BlobStoreConfig.java @@ -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"; diff --git a/apex/blobstore/service/java/com/android/server/blob/BlobStoreManagerService.java b/apex/blobstore/service/java/com/android/server/blob/BlobStoreManagerService.java index 05c661127eab..b202e95ed211 100644 --- a/apex/blobstore/service/java/com/android/server/blob/BlobStoreManagerService.java +++ b/apex/blobstore/service/java/com/android/server/blob/BlobStoreManagerService.java @@ -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; @@ -1181,8 +1182,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 |