Merge "Don't persist description res ids as they are subject to change." into rvc-dev

This commit is contained in:
Sudheer Shanka
2020-03-06 22:33:44 +00:00
committed by Android (Google) Code Review
5 changed files with 113 additions and 30 deletions

View File

@@ -145,6 +145,9 @@ public class BlobStoreManager {
/** @hide */ /** @hide */
public static final int INVALID_RES_ID = -1; public static final int INVALID_RES_ID = -1;
/** @hide */
public static final String DESC_RES_TYPE_STRING = "string";
private final Context mContext; private final Context mContext;
private final IBlobStoreManager mService; 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 * <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. * 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 * @param blobHandle the {@link BlobHandle} representing the blob that the caller wants to
* acquire a lease for. * acquire a lease for.
* @param descriptionResId the resource id for a short description string that can be surfaced * @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 * <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. * 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 * @param blobHandle the {@link BlobHandle} representing the blob that the caller wants to
* acquire a lease for. * acquire a lease for.
* @param descriptionResId the resource id for a short description string that can be surfaced * @param descriptionResId the resource id for a short description string that can be surfaced

View File

@@ -51,6 +51,6 @@ public final class XmlTags {
// For leasee // For leasee
public static final String TAG_LEASEE = "l"; 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"; public static final String ATTR_DESCRIPTION = "d";
} }

View File

@@ -15,8 +15,9 @@
*/ */
package com.android.server.blob; 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;
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_EXPIRY_TIME;
import static android.app.blob.XmlTags.ATTR_ID; import static android.app.blob.XmlTags.ATTR_ID;
import static android.app.blob.XmlTags.ATTR_PACKAGE; 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.os.Process.INVALID_UID;
import static android.system.OsConstants.O_RDONLY; 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.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 static com.android.server.blob.BlobStoreConfig.XML_VERSION_ADD_STRING_DESC;
import android.annotation.NonNull; import android.annotation.NonNull;
@@ -154,7 +157,7 @@ class BlobMetadata {
synchronized (mMetadataLock) { synchronized (mMetadataLock) {
// We need to override the leasee data, so first remove any existing // We need to override the leasee data, so first remove any existing
// leasee before adding the new one. // leasee before adding the new one.
final Leasee leasee = new Leasee(callingPackage, callingUid, final Leasee leasee = new Leasee(mContext, callingPackage, callingUid,
descriptionResId, description, leaseExpiryTimeMillis); descriptionResId, description, leaseExpiryTimeMillis);
mLeasees.remove(leasee); mLeasees.remove(leasee);
mLeasees.add(leasee); mLeasees.add(leasee);
@@ -459,59 +462,123 @@ class BlobMetadata {
} }
static final class Leasee extends Accessor { static final class Leasee extends Accessor {
public final int descriptionResId; public final String descriptionResEntryName;
public final CharSequence description; public final CharSequence description;
public final long expiryTimeMillis; public final long expiryTimeMillis;
Leasee(String packageName, int uid, int descriptionResId, CharSequence description, Leasee(@NonNull Context context, @NonNull String packageName,
long expiryTimeMillis) { int uid, int descriptionResId,
@Nullable CharSequence description, long expiryTimeMillis) {
super(packageName, uid); 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.expiryTimeMillis = expiryTimeMillis;
this.description = description; 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() { boolean isStillValid() {
return expiryTimeMillis == 0 || expiryTimeMillis <= System.currentTimeMillis(); 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("desc: " + getDescriptionToDump(context));
fout.println("expiryMs: " + expiryTimeMillis); fout.println("expiryMs: " + expiryTimeMillis);
} }
private String getDescriptionToDump(Context context) { @NonNull
String desc = null; private String getDescriptionToDump(@NonNull Context context) {
if (ResourceId.isValid(descriptionResId)) { String desc = getDescription(context, descriptionResEntryName, packageName,
try { UserHandle.getUserId(uid));
final Resources leaseeRes = context.getPackageManager() if (desc == null) {
.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 {
desc = description.toString(); 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 { void writeToXml(@NonNull XmlSerializer out) throws IOException {
XmlUtils.writeStringAttribute(out, ATTR_PACKAGE, packageName); XmlUtils.writeStringAttribute(out, ATTR_PACKAGE, packageName);
XmlUtils.writeIntAttribute(out, ATTR_UID, uid); 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.writeLongAttribute(out, ATTR_EXPIRY_TIME, expiryTimeMillis);
XmlUtils.writeStringAttribute(out, ATTR_DESCRIPTION, description); XmlUtils.writeStringAttribute(out, ATTR_DESCRIPTION, description);
} }
@NonNull @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 String packageName = XmlUtils.readStringAttribute(in, ATTR_PACKAGE);
final int uid = XmlUtils.readIntAttribute(in, ATTR_UID); 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 long expiryTimeMillis = XmlUtils.readLongAttribute(in, ATTR_EXPIRY_TIME);
final CharSequence description; final CharSequence description;
if (version >= XML_VERSION_ADD_STRING_DESC) { if (version >= XML_VERSION_ADD_STRING_DESC) {
@@ -520,7 +587,8 @@ class BlobMetadata {
description = null; description = null;
} }
return new Leasee(packageName, uid, descriptionResId, description, expiryTimeMillis); return new Leasee(packageName, uid, descriptionResEntryName,
description, expiryTimeMillis);
} }
} }

View File

@@ -32,8 +32,9 @@ class BlobStoreConfig {
public static final int XML_VERSION_INIT = 1; public static final int XML_VERSION_INIT = 1;
// Added a string variant of lease description. // Added a string variant of lease description.
public static final int XML_VERSION_ADD_STRING_DESC = 2; 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 ROOT_DIR_NAME = "blobstore";
private static final String BLOBS_DIR_NAME = "blobs"; private static final String BLOBS_DIR_NAME = "blobs";

View File

@@ -54,6 +54,7 @@ import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManagerInternal; import android.content.pm.PackageManagerInternal;
import android.content.pm.PackageStats; import android.content.pm.PackageStats;
import android.content.res.ResourceId; import android.content.res.ResourceId;
import android.content.res.Resources;
import android.os.Binder; import android.os.Binder;
import android.os.Handler; import android.os.Handler;
import android.os.HandlerThread; import android.os.HandlerThread;
@@ -1187,8 +1188,12 @@ public class BlobStoreManagerService extends SystemService {
final int callingUid = Binder.getCallingUid(); final int callingUid = Binder.getCallingUid();
verifyCallingPackage(callingUid, packageName); verifyCallingPackage(callingUid, packageName);
acquireLeaseInternal(blobHandle, descriptionResId, description, leaseExpiryTimeMillis, try {
callingUid, packageName); acquireLeaseInternal(blobHandle, descriptionResId, description,
leaseExpiryTimeMillis, callingUid, packageName);
} catch (Resources.NotFoundException e) {
throw new IllegalArgumentException(e);
}
} }
@Override @Override