Loading apex/blobstore/framework/java/android/app/blob/BlobHandle.java +47 −0 Original line number Diff line number Diff line Loading @@ -15,13 +15,26 @@ */ package android.app.blob; import static android.app.blob.XmlTags.ATTR_ALGO; import static android.app.blob.XmlTags.ATTR_DIGEST; import static android.app.blob.XmlTags.ATTR_EXPIRY_TIME; import static android.app.blob.XmlTags.ATTR_LABEL; import static android.app.blob.XmlTags.ATTR_TAG; import android.annotation.CurrentTimeMillisLong; import android.annotation.NonNull; import android.os.Parcel; import android.os.Parcelable; import android.util.Base64; import com.android.internal.util.IndentingPrintWriter; import com.android.internal.util.Preconditions; import com.android.internal.util.XmlUtils; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlSerializer; import java.io.IOException; import java.util.Arrays; import java.util.Objects; Loading @@ -41,17 +54,20 @@ public final class BlobHandle implements Parcelable { * @hide */ @NonNull public final String algorithm; /** * Hash of the blob this handle is representing using {@link #algorithm}. * * @hide */ @NonNull public final byte[] digest; /** * Label of the blob that can be surfaced to the user. * @hide */ @NonNull public final CharSequence label; /** * Time in milliseconds after which the blob should be invalidated and not * allowed to be accessed by any other app, in {@link System#currentTimeMillis()} timebase. Loading @@ -59,6 +75,7 @@ public final class BlobHandle implements Parcelable { * @hide */ @CurrentTimeMillisLong public final long expiryTimeMillis; /** * An opaque {@link String} associated with the blob. * Loading Loading @@ -197,6 +214,15 @@ public final class BlobHandle implements Parcelable { return Objects.hash(algorithm, Arrays.hashCode(digest), label, expiryTimeMillis, tag); } /** @hide */ public void dump(IndentingPrintWriter fout) { fout.println("algo: " + algorithm); fout.println("digest: " + Base64.encodeToString(digest, Base64.NO_WRAP)); fout.println("label: " + label); fout.println("expiryMs: " + expiryTimeMillis); fout.println("tag: " + tag); } public static final @NonNull Creator<BlobHandle> CREATOR = new Creator<BlobHandle>() { @Override public @NonNull BlobHandle createFromParcel(@NonNull Parcel source) { Loading @@ -208,4 +234,25 @@ public final class BlobHandle implements Parcelable { return new BlobHandle[size]; } }; /** @hide */ public void writeToXml(@NonNull XmlSerializer out) throws IOException { XmlUtils.writeStringAttribute(out, ATTR_ALGO, algorithm); XmlUtils.writeByteArrayAttribute(out, ATTR_DIGEST, digest); XmlUtils.writeStringAttribute(out, ATTR_LABEL, label); XmlUtils.writeLongAttribute(out, ATTR_EXPIRY_TIME, expiryTimeMillis); XmlUtils.writeStringAttribute(out, ATTR_TAG, tag); } /** @hide */ @NonNull public static BlobHandle createFromXml(@NonNull XmlPullParser in) throws IOException { final String algo = XmlUtils.readStringAttribute(in, ATTR_ALGO); final byte[] digest = XmlUtils.readByteArrayAttribute(in, ATTR_DIGEST); final CharSequence label = XmlUtils.readStringAttribute(in, ATTR_LABEL); final long expiryTimeMs = XmlUtils.readLongAttribute(in, ATTR_EXPIRY_TIME); final String tag = XmlUtils.readStringAttribute(in, ATTR_TAG); return BlobHandle.create(algo, digest, label, expiryTimeMs, tag); } } apex/blobstore/framework/java/android/app/blob/BlobStoreManager.java +23 −0 Original line number Diff line number Diff line Loading @@ -25,13 +25,17 @@ import android.annotation.SystemService; import android.content.Context; import android.os.ParcelFileDescriptor; import android.os.ParcelableException; import android.os.RemoteCallback; import android.os.RemoteException; import com.android.internal.util.function.pooled.PooledLambda; import java.io.Closeable; import java.io.IOException; import java.util.concurrent.CountDownLatch; import java.util.concurrent.Executor; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import java.util.function.Consumer; /** Loading Loading @@ -352,6 +356,25 @@ public class BlobStoreManager { } } /** * Wait until any pending tasks (like persisting data to disk) have finished. * * @hide */ public void waitForIdle(long timeoutMillis) throws InterruptedException, TimeoutException { try { final CountDownLatch countDownLatch = new CountDownLatch(1); mService.waitForIdle(new RemoteCallback((result) -> countDownLatch.countDown())); if (!countDownLatch.await(timeoutMillis, TimeUnit.MILLISECONDS)) { throw new TimeoutException("Timed out waiting for service to become idle"); } } catch (ParcelableException e) { throw new RuntimeException(e); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * Represents an ongoing session of a blob's contribution to the blob store managed by the * system. Loading apex/blobstore/framework/java/android/app/blob/IBlobStoreManager.aidl +3 −0 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package android.app.blob; import android.app.blob.BlobHandle; import android.app.blob.IBlobStoreSession; import android.os.RemoteCallback; /** {@hide} */ interface IBlobStoreManager { Loading @@ -28,4 +29,6 @@ interface IBlobStoreManager { void acquireLease(in BlobHandle handle, int descriptionResId, long leaseTimeout, in String packageName); void releaseLease(in BlobHandle handle, in String packageName); void waitForIdle(in RemoteCallback callback); } No newline at end of file apex/blobstore/framework/java/android/app/blob/XmlTags.java 0 → 100644 +55 −0 Original line number Diff line number Diff line /* * Copyright 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 android.app.blob; /** @hide */ public final class XmlTags { public static final String ATTR_VERSION = "v"; public static final String TAG_SESSIONS = "ss"; public static final String TAG_BLOBS = "bs"; // For BlobStoreSession public static final String TAG_SESSION = "s"; public static final String ATTR_ID = "id"; public static final String ATTR_PACKAGE = "p"; public static final String ATTR_UID = "u"; // For BlobMetadata public static final String TAG_BLOB = "b"; public static final String ATTR_USER_ID = "us"; // For BlobAccessMode public static final String TAG_ACCESS_MODE = "am"; public static final String ATTR_TYPE = "t"; public static final String TAG_WHITELISTED_PACKAGE = "wl"; public static final String ATTR_CERTIFICATE = "ct"; // For BlobHandle public static final String TAG_BLOB_HANDLE = "bh"; public static final String ATTR_ALGO = "al"; public static final String ATTR_DIGEST = "dg"; public static final String ATTR_LABEL = "lbl"; public static final String ATTR_EXPIRY_TIME = "ex"; public static final String ATTR_TAG = "tg"; // For committer public static final String TAG_COMMITTER = "c"; // For leasee public static final String TAG_LEASEE = "l"; public static final String ATTR_DESCRIPTION_RES_ID = "rid"; } apex/blobstore/service/java/com/android/server/blob/BlobAccessMode.java +70 −4 Original line number Diff line number Diff line Loading @@ -15,12 +15,27 @@ */ package com.android.server.blob; import static android.app.blob.XmlTags.ATTR_CERTIFICATE; import static android.app.blob.XmlTags.ATTR_PACKAGE; import static android.app.blob.XmlTags.ATTR_TYPE; import static android.app.blob.XmlTags.TAG_WHITELISTED_PACKAGE; import android.annotation.IntDef; import android.annotation.NonNull; import android.content.Context; import android.content.pm.PackageManager; import android.util.ArraySet; import android.util.Base64; import android.util.DebugUtils; import com.android.internal.util.IndentingPrintWriter; import com.android.internal.util.XmlUtils; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlSerializer; import java.io.IOException; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.Arrays; Loading @@ -40,10 +55,10 @@ class BlobAccessMode { ACCESS_TYPE_WHITELIST, }) @interface AccessType {} static final int ACCESS_TYPE_PRIVATE = 1 << 0; static final int ACCESS_TYPE_PUBLIC = 1 << 1; static final int ACCESS_TYPE_SAME_SIGNATURE = 1 << 2; static final int ACCESS_TYPE_WHITELIST = 1 << 3; public static final int ACCESS_TYPE_PRIVATE = 1 << 0; public static final int ACCESS_TYPE_PUBLIC = 1 << 1; public static final int ACCESS_TYPE_SAME_SIGNATURE = 1 << 2; public static final int ACCESS_TYPE_WHITELIST = 1 << 3; private int mAccessType = ACCESS_TYPE_PRIVATE; Loading Loading @@ -112,6 +127,51 @@ class BlobAccessMode { return false; } void dump(IndentingPrintWriter fout) { fout.println("accessType: " + DebugUtils.flagsToString( BlobAccessMode.class, "ACCESS_TYPE_", mAccessType)); fout.print("Whitelisted pkgs:"); if (mWhitelistedPackages.isEmpty()) { fout.println(" (Empty)"); } else { fout.increaseIndent(); for (int i = 0, count = mWhitelistedPackages.size(); i < count; ++i) { fout.println(mWhitelistedPackages.valueAt(i).toString()); } fout.decreaseIndent(); } } void writeToXml(@NonNull XmlSerializer out) throws IOException { XmlUtils.writeIntAttribute(out, ATTR_TYPE, mAccessType); for (int i = 0, count = mWhitelistedPackages.size(); i < count; ++i) { out.startTag(null, TAG_WHITELISTED_PACKAGE); final PackageIdentifier packageIdentifier = mWhitelistedPackages.valueAt(i); XmlUtils.writeStringAttribute(out, ATTR_PACKAGE, packageIdentifier.packageName); XmlUtils.writeByteArrayAttribute(out, ATTR_CERTIFICATE, packageIdentifier.certificate); out.endTag(null, TAG_WHITELISTED_PACKAGE); } } @NonNull static BlobAccessMode createFromXml(@NonNull XmlPullParser in) throws IOException, XmlPullParserException { final BlobAccessMode blobAccessMode = new BlobAccessMode(); final int accessType = XmlUtils.readIntAttribute(in, ATTR_TYPE); blobAccessMode.mAccessType = accessType; final int depth = in.getDepth(); while (XmlUtils.nextElementWithin(in, depth)) { if (TAG_WHITELISTED_PACKAGE.equals(in.getName())) { final String packageName = XmlUtils.readStringAttribute(in, ATTR_PACKAGE); final byte[] certificate = XmlUtils.readByteArrayAttribute(in, ATTR_CERTIFICATE); blobAccessMode.allowPackageAccess(packageName, certificate); } } return blobAccessMode; } private static final class PackageIdentifier { public final String packageName; public final byte[] certificate; Loading Loading @@ -143,5 +203,11 @@ class BlobAccessMode { public int hashCode() { return Objects.hash(packageName, Arrays.hashCode(certificate)); } @Override public String toString() { return "[" + packageName + ", " + Base64.encodeToString(certificate, Base64.NO_WRAP) + "]"; } } } Loading
apex/blobstore/framework/java/android/app/blob/BlobHandle.java +47 −0 Original line number Diff line number Diff line Loading @@ -15,13 +15,26 @@ */ package android.app.blob; import static android.app.blob.XmlTags.ATTR_ALGO; import static android.app.blob.XmlTags.ATTR_DIGEST; import static android.app.blob.XmlTags.ATTR_EXPIRY_TIME; import static android.app.blob.XmlTags.ATTR_LABEL; import static android.app.blob.XmlTags.ATTR_TAG; import android.annotation.CurrentTimeMillisLong; import android.annotation.NonNull; import android.os.Parcel; import android.os.Parcelable; import android.util.Base64; import com.android.internal.util.IndentingPrintWriter; import com.android.internal.util.Preconditions; import com.android.internal.util.XmlUtils; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlSerializer; import java.io.IOException; import java.util.Arrays; import java.util.Objects; Loading @@ -41,17 +54,20 @@ public final class BlobHandle implements Parcelable { * @hide */ @NonNull public final String algorithm; /** * Hash of the blob this handle is representing using {@link #algorithm}. * * @hide */ @NonNull public final byte[] digest; /** * Label of the blob that can be surfaced to the user. * @hide */ @NonNull public final CharSequence label; /** * Time in milliseconds after which the blob should be invalidated and not * allowed to be accessed by any other app, in {@link System#currentTimeMillis()} timebase. Loading @@ -59,6 +75,7 @@ public final class BlobHandle implements Parcelable { * @hide */ @CurrentTimeMillisLong public final long expiryTimeMillis; /** * An opaque {@link String} associated with the blob. * Loading Loading @@ -197,6 +214,15 @@ public final class BlobHandle implements Parcelable { return Objects.hash(algorithm, Arrays.hashCode(digest), label, expiryTimeMillis, tag); } /** @hide */ public void dump(IndentingPrintWriter fout) { fout.println("algo: " + algorithm); fout.println("digest: " + Base64.encodeToString(digest, Base64.NO_WRAP)); fout.println("label: " + label); fout.println("expiryMs: " + expiryTimeMillis); fout.println("tag: " + tag); } public static final @NonNull Creator<BlobHandle> CREATOR = new Creator<BlobHandle>() { @Override public @NonNull BlobHandle createFromParcel(@NonNull Parcel source) { Loading @@ -208,4 +234,25 @@ public final class BlobHandle implements Parcelable { return new BlobHandle[size]; } }; /** @hide */ public void writeToXml(@NonNull XmlSerializer out) throws IOException { XmlUtils.writeStringAttribute(out, ATTR_ALGO, algorithm); XmlUtils.writeByteArrayAttribute(out, ATTR_DIGEST, digest); XmlUtils.writeStringAttribute(out, ATTR_LABEL, label); XmlUtils.writeLongAttribute(out, ATTR_EXPIRY_TIME, expiryTimeMillis); XmlUtils.writeStringAttribute(out, ATTR_TAG, tag); } /** @hide */ @NonNull public static BlobHandle createFromXml(@NonNull XmlPullParser in) throws IOException { final String algo = XmlUtils.readStringAttribute(in, ATTR_ALGO); final byte[] digest = XmlUtils.readByteArrayAttribute(in, ATTR_DIGEST); final CharSequence label = XmlUtils.readStringAttribute(in, ATTR_LABEL); final long expiryTimeMs = XmlUtils.readLongAttribute(in, ATTR_EXPIRY_TIME); final String tag = XmlUtils.readStringAttribute(in, ATTR_TAG); return BlobHandle.create(algo, digest, label, expiryTimeMs, tag); } }
apex/blobstore/framework/java/android/app/blob/BlobStoreManager.java +23 −0 Original line number Diff line number Diff line Loading @@ -25,13 +25,17 @@ import android.annotation.SystemService; import android.content.Context; import android.os.ParcelFileDescriptor; import android.os.ParcelableException; import android.os.RemoteCallback; import android.os.RemoteException; import com.android.internal.util.function.pooled.PooledLambda; import java.io.Closeable; import java.io.IOException; import java.util.concurrent.CountDownLatch; import java.util.concurrent.Executor; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import java.util.function.Consumer; /** Loading Loading @@ -352,6 +356,25 @@ public class BlobStoreManager { } } /** * Wait until any pending tasks (like persisting data to disk) have finished. * * @hide */ public void waitForIdle(long timeoutMillis) throws InterruptedException, TimeoutException { try { final CountDownLatch countDownLatch = new CountDownLatch(1); mService.waitForIdle(new RemoteCallback((result) -> countDownLatch.countDown())); if (!countDownLatch.await(timeoutMillis, TimeUnit.MILLISECONDS)) { throw new TimeoutException("Timed out waiting for service to become idle"); } } catch (ParcelableException e) { throw new RuntimeException(e); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * Represents an ongoing session of a blob's contribution to the blob store managed by the * system. Loading
apex/blobstore/framework/java/android/app/blob/IBlobStoreManager.aidl +3 −0 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package android.app.blob; import android.app.blob.BlobHandle; import android.app.blob.IBlobStoreSession; import android.os.RemoteCallback; /** {@hide} */ interface IBlobStoreManager { Loading @@ -28,4 +29,6 @@ interface IBlobStoreManager { void acquireLease(in BlobHandle handle, int descriptionResId, long leaseTimeout, in String packageName); void releaseLease(in BlobHandle handle, in String packageName); void waitForIdle(in RemoteCallback callback); } No newline at end of file
apex/blobstore/framework/java/android/app/blob/XmlTags.java 0 → 100644 +55 −0 Original line number Diff line number Diff line /* * Copyright 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 android.app.blob; /** @hide */ public final class XmlTags { public static final String ATTR_VERSION = "v"; public static final String TAG_SESSIONS = "ss"; public static final String TAG_BLOBS = "bs"; // For BlobStoreSession public static final String TAG_SESSION = "s"; public static final String ATTR_ID = "id"; public static final String ATTR_PACKAGE = "p"; public static final String ATTR_UID = "u"; // For BlobMetadata public static final String TAG_BLOB = "b"; public static final String ATTR_USER_ID = "us"; // For BlobAccessMode public static final String TAG_ACCESS_MODE = "am"; public static final String ATTR_TYPE = "t"; public static final String TAG_WHITELISTED_PACKAGE = "wl"; public static final String ATTR_CERTIFICATE = "ct"; // For BlobHandle public static final String TAG_BLOB_HANDLE = "bh"; public static final String ATTR_ALGO = "al"; public static final String ATTR_DIGEST = "dg"; public static final String ATTR_LABEL = "lbl"; public static final String ATTR_EXPIRY_TIME = "ex"; public static final String ATTR_TAG = "tg"; // For committer public static final String TAG_COMMITTER = "c"; // For leasee public static final String TAG_LEASEE = "l"; public static final String ATTR_DESCRIPTION_RES_ID = "rid"; }
apex/blobstore/service/java/com/android/server/blob/BlobAccessMode.java +70 −4 Original line number Diff line number Diff line Loading @@ -15,12 +15,27 @@ */ package com.android.server.blob; import static android.app.blob.XmlTags.ATTR_CERTIFICATE; import static android.app.blob.XmlTags.ATTR_PACKAGE; import static android.app.blob.XmlTags.ATTR_TYPE; import static android.app.blob.XmlTags.TAG_WHITELISTED_PACKAGE; import android.annotation.IntDef; import android.annotation.NonNull; import android.content.Context; import android.content.pm.PackageManager; import android.util.ArraySet; import android.util.Base64; import android.util.DebugUtils; import com.android.internal.util.IndentingPrintWriter; import com.android.internal.util.XmlUtils; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlSerializer; import java.io.IOException; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.Arrays; Loading @@ -40,10 +55,10 @@ class BlobAccessMode { ACCESS_TYPE_WHITELIST, }) @interface AccessType {} static final int ACCESS_TYPE_PRIVATE = 1 << 0; static final int ACCESS_TYPE_PUBLIC = 1 << 1; static final int ACCESS_TYPE_SAME_SIGNATURE = 1 << 2; static final int ACCESS_TYPE_WHITELIST = 1 << 3; public static final int ACCESS_TYPE_PRIVATE = 1 << 0; public static final int ACCESS_TYPE_PUBLIC = 1 << 1; public static final int ACCESS_TYPE_SAME_SIGNATURE = 1 << 2; public static final int ACCESS_TYPE_WHITELIST = 1 << 3; private int mAccessType = ACCESS_TYPE_PRIVATE; Loading Loading @@ -112,6 +127,51 @@ class BlobAccessMode { return false; } void dump(IndentingPrintWriter fout) { fout.println("accessType: " + DebugUtils.flagsToString( BlobAccessMode.class, "ACCESS_TYPE_", mAccessType)); fout.print("Whitelisted pkgs:"); if (mWhitelistedPackages.isEmpty()) { fout.println(" (Empty)"); } else { fout.increaseIndent(); for (int i = 0, count = mWhitelistedPackages.size(); i < count; ++i) { fout.println(mWhitelistedPackages.valueAt(i).toString()); } fout.decreaseIndent(); } } void writeToXml(@NonNull XmlSerializer out) throws IOException { XmlUtils.writeIntAttribute(out, ATTR_TYPE, mAccessType); for (int i = 0, count = mWhitelistedPackages.size(); i < count; ++i) { out.startTag(null, TAG_WHITELISTED_PACKAGE); final PackageIdentifier packageIdentifier = mWhitelistedPackages.valueAt(i); XmlUtils.writeStringAttribute(out, ATTR_PACKAGE, packageIdentifier.packageName); XmlUtils.writeByteArrayAttribute(out, ATTR_CERTIFICATE, packageIdentifier.certificate); out.endTag(null, TAG_WHITELISTED_PACKAGE); } } @NonNull static BlobAccessMode createFromXml(@NonNull XmlPullParser in) throws IOException, XmlPullParserException { final BlobAccessMode blobAccessMode = new BlobAccessMode(); final int accessType = XmlUtils.readIntAttribute(in, ATTR_TYPE); blobAccessMode.mAccessType = accessType; final int depth = in.getDepth(); while (XmlUtils.nextElementWithin(in, depth)) { if (TAG_WHITELISTED_PACKAGE.equals(in.getName())) { final String packageName = XmlUtils.readStringAttribute(in, ATTR_PACKAGE); final byte[] certificate = XmlUtils.readByteArrayAttribute(in, ATTR_CERTIFICATE); blobAccessMode.allowPackageAccess(packageName, certificate); } } return blobAccessMode; } private static final class PackageIdentifier { public final String packageName; public final byte[] certificate; Loading Loading @@ -143,5 +203,11 @@ class BlobAccessMode { public int hashCode() { return Objects.hash(packageName, Arrays.hashCode(certificate)); } @Override public String toString() { return "[" + packageName + ", " + Base64.encodeToString(certificate, Base64.NO_WRAP) + "]"; } } }