summaryrefslogtreecommitdiff
path: root/apex/blobstore/service/java
diff options
context:
space:
mode:
authorSudheer Shanka <sudheersai@google.com>2020-03-04 13:54:36 -0800
committerSudheer Shanka <sudheersai@google.com>2020-03-09 11:05:53 -0700
commit130d79cc8b05e82fbaf0172ececfcea6d159460c (patch)
tree0057f1ba843be32e762143b6589228628ce29d7a /apex/blobstore/service/java
parent606626e020abd13b87af7e2db59f6dafaef24452 (diff)
Add hidden APIs to query and delete shared blobs.
Bug: 150804006 Test: atest --test-mapping apex/blobstore Change-Id: Ia445715879c1b6ec74c2a2ee9d2ff0eb1f4ee72b
Diffstat (limited to 'apex/blobstore/service/java')
-rw-r--r--apex/blobstore/service/java/com/android/server/blob/BlobMetadata.java36
-rw-r--r--apex/blobstore/service/java/com/android/server/blob/BlobStoreManagerService.java70
-rw-r--r--apex/blobstore/service/java/com/android/server/blob/BlobStoreUtils.java50
3 files changed, 130 insertions, 26 deletions
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 dab4797b313f..970766d2c8a6 100644
--- a/apex/blobstore/service/java/com/android/server/blob/BlobMetadata.java
+++ b/apex/blobstore/service/java/com/android/server/blob/BlobMetadata.java
@@ -15,7 +15,6 @@
*/
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_NAME;
import static android.app.blob.XmlTags.ATTR_EXPIRY_TIME;
@@ -30,16 +29,16 @@ 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 static com.android.server.blob.BlobStoreUtils.getDescriptionResourceId;
+import static com.android.server.blob.BlobStoreUtils.getPackageResources;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.blob.BlobHandle;
import android.content.Context;
-import android.content.pm.PackageManager;
import android.content.res.ResourceId;
import android.content.res.Resources;
import android.os.ParcelFileDescriptor;
@@ -65,6 +64,7 @@ import java.io.File;
import java.io.FileDescriptor;
import java.io.IOException;
import java.util.Objects;
+import java.util.function.Consumer;
class BlobMetadata {
private final Object mMetadataLock = new Object();
@@ -281,6 +281,10 @@ class BlobMetadata {
return false;
}
+ void forEachLeasee(Consumer<Leasee> consumer) {
+ mLeasees.forEach(consumer);
+ }
+
File getBlobFile() {
if (mBlobFile == null) {
mBlobFile = BlobStoreConfig.getBlobFile(mBlobId);
@@ -506,16 +510,9 @@ class BlobMetadata {
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;
- }
+ final int resId = getDescriptionResourceId(resources, descriptionResEntryName,
+ packageName);
+ return resId == Resources.ID_NULL ? null : resources.getString(resId);
}
@Nullable
@@ -546,19 +543,6 @@ class BlobMetadata {
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);
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 96f7b7aee165..ed3dda44e131 100644
--- a/apex/blobstore/service/java/com/android/server/blob/BlobStoreManagerService.java
+++ b/apex/blobstore/service/java/com/android/server/blob/BlobStoreManagerService.java
@@ -36,6 +36,8 @@ import static com.android.server.blob.BlobStoreSession.STATE_COMMITTED;
import static com.android.server.blob.BlobStoreSession.STATE_VERIFIED_INVALID;
import static com.android.server.blob.BlobStoreSession.STATE_VERIFIED_VALID;
import static com.android.server.blob.BlobStoreSession.stateToString;
+import static com.android.server.blob.BlobStoreUtils.getDescriptionResourceId;
+import static com.android.server.blob.BlobStoreUtils.getPackageResources;
import android.annotation.CurrentTimeSecondsLong;
import android.annotation.IdRes;
@@ -43,7 +45,9 @@ import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
+import android.app.blob.AccessorInfo;
import android.app.blob.BlobHandle;
+import android.app.blob.BlobInfo;
import android.app.blob.IBlobStoreManager;
import android.app.blob.IBlobStoreSession;
import android.content.BroadcastReceiver;
@@ -100,6 +104,7 @@ import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
+import java.lang.ref.WeakReference;
import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;
import java.util.ArrayList;
@@ -110,6 +115,7 @@ import java.util.Random;
import java.util.Set;
import java.util.concurrent.atomic.AtomicLong;
import java.util.function.Consumer;
+import java.util.function.Function;
/**
* Service responsible for maintaining and facilitating access to data blobs published by apps.
@@ -434,6 +440,48 @@ public class BlobStoreManagerService extends SystemService {
}
}
+ private List<BlobInfo> queryBlobsForUserInternal(int userId) {
+ final ArrayList<BlobInfo> blobInfos = new ArrayList<>();
+ synchronized (mBlobsLock) {
+ final ArrayMap<String, WeakReference<Resources>> resources = new ArrayMap<>();
+ final Function<String, Resources> resourcesGetter = (packageName) -> {
+ final WeakReference<Resources> resourcesRef = resources.get(packageName);
+ Resources packageResources = resourcesRef == null ? null : resourcesRef.get();
+ if (packageResources == null) {
+ packageResources = getPackageResources(mContext, packageName, userId);
+ resources.put(packageName, new WeakReference<>(packageResources));
+ }
+ return packageResources;
+ };
+ getUserBlobsLocked(userId).forEach((blobHandle, blobMetadata) -> {
+ final ArrayList<AccessorInfo> accessorInfos = new ArrayList<>();
+ blobMetadata.forEachLeasee(leasee -> {
+ final int descriptionResId = leasee.descriptionResEntryName == null
+ ? Resources.ID_NULL
+ : getDescriptionResourceId(resourcesGetter.apply(leasee.packageName),
+ leasee.descriptionResEntryName, leasee.packageName);
+ accessorInfos.add(new AccessorInfo(leasee.packageName, leasee.expiryTimeMillis,
+ descriptionResId, leasee.description));
+ });
+ blobInfos.add(new BlobInfo(blobMetadata.getBlobId(),
+ blobHandle.getExpiryTimeMillis(), blobHandle.getLabel(), accessorInfos));
+ });
+ }
+ return blobInfos;
+ }
+
+ private void deleteBlobInternal(long blobId, int callingUid) {
+ synchronized (mBlobsLock) {
+ final ArrayMap<BlobHandle, BlobMetadata> userBlobs = getUserBlobsLocked(
+ UserHandle.getUserId(callingUid));
+ userBlobs.entrySet().removeIf(entry -> {
+ final BlobMetadata blobMetadata = entry.getValue();
+ return blobMetadata.getBlobId() == blobId;
+ });
+ writeBlobsInfoAsync();
+ }
+ }
+
private void verifyCallingPackage(int callingUid, String callingPackage) {
if (mPackageManagerInternal.getPackageUid(
callingPackage, 0, UserHandle.getUserId(callingUid)) != callingUid) {
@@ -1250,6 +1298,28 @@ public class BlobStoreManagerService extends SystemService {
}
@Override
+ @NonNull
+ public List<BlobInfo> queryBlobsForUser(@UserIdInt int userId) {
+ if (Binder.getCallingUid() != Process.SYSTEM_UID) {
+ throw new SecurityException("Only system uid is allowed to call "
+ + "queryBlobsForUser()");
+ }
+
+ return queryBlobsForUserInternal(userId);
+ }
+
+ @Override
+ public void deleteBlob(long blobId) {
+ final int callingUid = Binder.getCallingUid();
+ if (callingUid != Process.SYSTEM_UID) {
+ throw new SecurityException("Only system uid is allowed to call "
+ + "deleteBlob()");
+ }
+
+ deleteBlobInternal(blobId, callingUid);
+ }
+
+ @Override
public void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter writer,
@Nullable String[] args) {
// TODO: add proto-based version of this.
diff --git a/apex/blobstore/service/java/com/android/server/blob/BlobStoreUtils.java b/apex/blobstore/service/java/com/android/server/blob/BlobStoreUtils.java
new file mode 100644
index 000000000000..6af540acd6a4
--- /dev/null
+++ b/apex/blobstore/service/java/com/android/server/blob/BlobStoreUtils.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2020 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 com.android.server.blob;
+
+import static com.android.server.blob.BlobStoreConfig.TAG;
+
+import android.annotation.IdRes;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.content.res.Resources;
+import android.util.Slog;
+
+class BlobStoreUtils {
+ private static final String DESC_RES_TYPE_STRING = "string";
+
+ @Nullable
+ 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;
+ }
+ }
+
+ @IdRes
+ static int getDescriptionResourceId(@NonNull Resources resources,
+ @NonNull String resourceEntryName, @NonNull String packageName) {
+ return resources.getIdentifier(resourceEntryName, DESC_RES_TYPE_STRING, packageName);
+ }
+}