Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a9d69b78 authored by android-build-team Robot's avatar android-build-team Robot
Browse files

Snap for 6587913 from 38da493a to rvc-release

Change-Id: I1320b0e70badfc186ec42c4d1d6a8b1ec4c7dad7
parents 27e2ac32 38da493a
Loading
Loading
Loading
Loading
+9 −1
Original line number Diff line number Diff line
@@ -44,7 +44,7 @@ import java.util.Objects;
/**
 * Class for representing how a blob can be shared.
 *
 * Note that this class is not thread-safe, callers need to take of synchronizing access.
 * Note that this class is not thread-safe, callers need to take care of synchronizing access.
 */
class BlobAccessMode {
    @Retention(RetentionPolicy.SOURCE)
@@ -127,6 +127,14 @@ class BlobAccessMode {
        return false;
    }

    int getAccessType() {
        return mAccessType;
    }

    int getNumWhitelistedPackages() {
        return mWhitelistedPackages.size();
    }

    void dump(IndentingPrintWriter fout) {
        fout.println("accessType: " + DebugUtils.flagsToString(
                BlobAccessMode.class, "ACCESS_TYPE_", mAccessType));
+53 −4
Original line number Diff line number Diff line
@@ -54,6 +54,8 @@ import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Slog;
import android.util.SparseArray;
import android.util.StatsEvent;
import android.util.proto.ProtoOutputStream;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
@@ -61,6 +63,8 @@ import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.XmlUtils;
import com.android.server.blob.BlobStoreManagerService.DumpArgs;

import libcore.io.IoUtils;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;
@@ -349,14 +353,16 @@ class BlobMetadata {
        } catch (ErrnoException e) {
            throw e.rethrowAsIOException();
        }
        synchronized (mMetadataLock) {
            return createRevocableFdLocked(fd, callingPackage);
        try {
            return createRevocableFd(fd, callingPackage);
        } catch (IOException e) {
            IoUtils.closeQuietly(fd);
            throw e;
        }
    }

    @GuardedBy("mMetadataLock")
    @NonNull
    private ParcelFileDescriptor createRevocableFdLocked(FileDescriptor fd,
    private ParcelFileDescriptor createRevocableFd(FileDescriptor fd,
            String callingPackage) throws IOException {
        final RevocableFileDescriptor revocableFd =
                new RevocableFileDescriptor(mContext, fd);
@@ -410,6 +416,49 @@ class BlobMetadata {
        return true;
    }

    StatsEvent dumpAsStatsEvent(int atomTag) {
        synchronized (mMetadataLock) {
            ProtoOutputStream proto = new ProtoOutputStream();
            // Write Committer data to proto format
            for (int i = 0, size = mCommitters.size(); i < size; ++i) {
                final Committer committer = mCommitters.valueAt(i);
                final long token = proto.start(
                        BlobStatsEventProto.BlobCommitterListProto.COMMITTER);
                proto.write(BlobStatsEventProto.BlobCommitterProto.UID, committer.uid);
                proto.write(BlobStatsEventProto.BlobCommitterProto.COMMIT_TIMESTAMP_MILLIS,
                        committer.commitTimeMs);
                proto.write(BlobStatsEventProto.BlobCommitterProto.ACCESS_MODE,
                        committer.blobAccessMode.getAccessType());
                proto.write(BlobStatsEventProto.BlobCommitterProto.NUM_WHITELISTED_PACKAGE,
                        committer.blobAccessMode.getNumWhitelistedPackages());
                proto.end(token);
            }
            final byte[] committersBytes = proto.getBytes();

            proto = new ProtoOutputStream();
            // Write Leasee data to proto format
            for (int i = 0, size = mLeasees.size(); i < size; ++i) {
                final Leasee leasee = mLeasees.valueAt(i);
                final long token = proto.start(BlobStatsEventProto.BlobLeaseeListProto.LEASEE);
                proto.write(BlobStatsEventProto.BlobLeaseeProto.UID, leasee.uid);
                proto.write(BlobStatsEventProto.BlobLeaseeProto.LEASE_EXPIRY_TIMESTAMP_MILLIS,
                        leasee.expiryTimeMillis);
                proto.end(token);
            }
            final byte[] leaseesBytes = proto.getBytes();

            // Construct the StatsEvent to represent this Blob
            return StatsEvent.newBuilder()
                    .setAtomId(atomTag)
                    .writeLong(mBlobId)
                    .writeLong(getSize())
                    .writeLong(mBlobHandle.getExpiryTimeMillis())
                    .writeByteArray(committersBytes)
                    .writeByteArray(leaseesBytes)
                    .build();
        }
    }

    void dump(IndentingPrintWriter fout, DumpArgs dumpArgs) {
        fout.println("blobHandle:");
        fout.increaseIndent();
+3 −0
Original line number Diff line number Diff line
@@ -49,6 +49,9 @@ class BlobStoreConfig {

    public static final int XML_VERSION_CURRENT = XML_VERSION_ADD_SESSION_CREATION_TIME;

    public static final long INVALID_BLOB_ID = 0;
    public static final long INVALID_BLOB_SIZE = 0;

    private static final String ROOT_DIR_NAME = "blobstore";
    private static final String BLOBS_DIR_NAME = "blobs";
    private static final String SESSIONS_INDEX_FILE_NAME = "sessions_index.xml";
+86 −1
Original line number Diff line number Diff line
@@ -28,6 +28,8 @@ import static android.content.pm.PackageManager.MATCH_UNINSTALLED_PACKAGES;
import static android.os.UserHandle.USER_CURRENT;
import static android.os.UserHandle.USER_NULL;

import static com.android.server.blob.BlobStoreConfig.INVALID_BLOB_ID;
import static com.android.server.blob.BlobStoreConfig.INVALID_BLOB_SIZE;
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_CURRENT;
@@ -48,6 +50,7 @@ import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.app.ActivityManager;
import android.app.ActivityManagerInternal;
import android.app.StatsManager;
import android.app.blob.BlobHandle;
import android.app.blob.BlobInfo;
import android.app.blob.IBlobStoreManager;
@@ -80,6 +83,7 @@ import android.util.ExceptionUtils;
import android.util.LongSparseArray;
import android.util.Slog;
import android.util.SparseArray;
import android.util.StatsEvent;
import android.util.Xml;

import com.android.internal.annotations.GuardedBy;
@@ -88,6 +92,7 @@ import com.android.internal.os.BackgroundThread;
import com.android.internal.util.CollectionUtils;
import com.android.internal.util.DumpUtils;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.FrameworkStatsLog;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.Preconditions;
import com.android.internal.util.XmlUtils;
@@ -159,6 +164,8 @@ public class BlobStoreManagerService extends SystemService {
            new SessionStateChangeListener();

    private PackageManagerInternal mPackageManagerInternal;
    private StatsManager mStatsManager;
    private StatsPullAtomCallbackImpl mStatsCallbackImpl = new StatsPullAtomCallbackImpl();

    private final Runnable mSaveBlobsInfoRunnable = this::writeBlobsInfo;
    private final Runnable mSaveSessionsRunnable = this::writeBlobSessions;
@@ -192,6 +199,7 @@ public class BlobStoreManagerService extends SystemService {
        LocalServices.addService(BlobStoreManagerInternal.class, new LocalService());

        mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class);
        mStatsManager = getContext().getSystemService(StatsManager.class);
        registerReceivers();
        LocalServices.getService(StorageStatsManagerInternal.class)
                .registerStorageStatsAugmenter(new BlobStorageStatsAugmenter(), TAG);
@@ -207,6 +215,7 @@ public class BlobStoreManagerService extends SystemService {
                readBlobSessionsLocked(allPackages);
                readBlobsInfoLocked(allPackages);
            }
            registerBlobStorePuller();
        } else if (phase == PHASE_BOOT_COMPLETED) {
            BlobStoreIdleJobService.schedule(mContext);
        }
@@ -219,7 +228,7 @@ public class BlobStoreManagerService extends SystemService {
        long sessionId;
        do {
            sessionId = Math.abs(mRandom.nextLong());
            if (mKnownBlobIds.indexOf(sessionId) < 0 && sessionId != 0) {
            if (mKnownBlobIds.indexOf(sessionId) < 0 && sessionId != INVALID_BLOB_ID) {
                return sessionId;
            }
        } while (n++ < 32);
@@ -376,9 +385,23 @@ public class BlobStoreManagerService extends SystemService {
                    .get(blobHandle);
            if (blobMetadata == null || !blobMetadata.isAccessAllowedForCaller(
                    callingPackage, callingUid)) {
                if (blobMetadata == null) {
                    FrameworkStatsLog.write(FrameworkStatsLog.BLOB_OPENED, callingUid,
                            INVALID_BLOB_ID, INVALID_BLOB_SIZE,
                            FrameworkStatsLog.BLOB_OPENED__RESULT__BLOB_DNE);
                } else {
                    FrameworkStatsLog.write(FrameworkStatsLog.BLOB_OPENED, callingUid,
                            blobMetadata.getBlobId(), blobMetadata.getSize(),
                            FrameworkStatsLog.BLOB_LEASED__RESULT__ACCESS_NOT_ALLOWED);
                }
                throw new SecurityException("Caller not allowed to access " + blobHandle
                        + "; callingUid=" + callingUid + ", callingPackage=" + callingPackage);
            }

            FrameworkStatsLog.write(FrameworkStatsLog.BLOB_OPENED, callingUid,
                    blobMetadata.getBlobId(), blobMetadata.getSize(),
                    FrameworkStatsLog.BLOB_OPENED__RESULT__SUCCESS);

            return blobMetadata.openForRead(callingPackage);
        }
    }
@@ -391,19 +414,41 @@ public class BlobStoreManagerService extends SystemService {
                    .get(blobHandle);
            if (blobMetadata == null || !blobMetadata.isAccessAllowedForCaller(
                    callingPackage, callingUid)) {
                if (blobMetadata == null) {
                    FrameworkStatsLog.write(FrameworkStatsLog.BLOB_LEASED, callingUid,
                            INVALID_BLOB_ID, INVALID_BLOB_SIZE,
                            FrameworkStatsLog.BLOB_LEASED__RESULT__BLOB_DNE);
                } else {
                    FrameworkStatsLog.write(FrameworkStatsLog.BLOB_LEASED, callingUid,
                            blobMetadata.getBlobId(), blobMetadata.getSize(),
                            FrameworkStatsLog.BLOB_LEASED__RESULT__ACCESS_NOT_ALLOWED);
                }
                throw new SecurityException("Caller not allowed to access " + blobHandle
                        + "; callingUid=" + callingUid + ", callingPackage=" + callingPackage);
            }
            if (leaseExpiryTimeMillis != 0 && blobHandle.expiryTimeMillis != 0
                    && leaseExpiryTimeMillis > blobHandle.expiryTimeMillis) {

                FrameworkStatsLog.write(FrameworkStatsLog.BLOB_LEASED, callingUid,
                        blobMetadata.getBlobId(), blobMetadata.getSize(),
                        FrameworkStatsLog.BLOB_LEASED__RESULT__LEASE_EXPIRY_INVALID);
                throw new IllegalArgumentException(
                        "Lease expiry cannot be later than blobs expiry time");
            }
            if (blobMetadata.getSize()
                    > getRemainingLeaseQuotaBytesInternal(callingUid, callingPackage)) {

                FrameworkStatsLog.write(FrameworkStatsLog.BLOB_LEASED, callingUid,
                        blobMetadata.getBlobId(), blobMetadata.getSize(),
                        FrameworkStatsLog.BLOB_LEASED__RESULT__DATA_SIZE_LIMIT_EXCEEDED);
                throw new LimitExceededException("Total amount of data with an active lease"
                        + " is exceeding the max limit");
            }

            FrameworkStatsLog.write(FrameworkStatsLog.BLOB_LEASED, callingUid,
                    blobMetadata.getBlobId(), blobMetadata.getSize(),
                    FrameworkStatsLog.BLOB_LEASED__RESULT__SUCCESS);

            blobMetadata.addOrReplaceLeasee(callingPackage, callingUid,
                    descriptionResId, description, leaseExpiryTimeMillis);
            if (LOGV) {
@@ -587,6 +632,9 @@ public class BlobStoreManagerService extends SystemService {
                    blob.addOrReplaceCommitter(newCommitter);
                    try {
                        writeBlobsInfoLocked();
                        FrameworkStatsLog.write(FrameworkStatsLog.BLOB_COMMITTED,
                                session.getOwnerUid(), blob.getBlobId(), blob.getSize(),
                                FrameworkStatsLog.BLOB_COMMITTED__RESULT__SUCCESS);
                        session.sendCommitCallbackResult(COMMIT_RESULT_SUCCESS);
                    } catch (Exception e) {
                        if (existingCommitter == null) {
@@ -595,6 +643,9 @@ public class BlobStoreManagerService extends SystemService {
                            blob.addOrReplaceCommitter(existingCommitter);
                        }
                        Slog.d(TAG, "Error committing the blob", e);
                        FrameworkStatsLog.write(FrameworkStatsLog.BLOB_COMMITTED,
                                session.getOwnerUid(), blob.getBlobId(), blob.getSize(),
                                FrameworkStatsLog.BLOB_COMMITTED__RESULT__ERROR_DURING_COMMIT);
                        session.sendCommitCallbackResult(COMMIT_RESULT_ERROR);
                    }
                    getUserSessionsLocked(UserHandle.getUserId(session.getOwnerUid()))
@@ -1684,6 +1735,40 @@ public class BlobStoreManagerService extends SystemService {
        }
    }

    private void registerBlobStorePuller() {
        mStatsManager.setPullAtomCallback(
                FrameworkStatsLog.BLOB_INFO,
                null, // use default PullAtomMetadata values
                BackgroundThread.getExecutor(),
                mStatsCallbackImpl
        );
    }

    private class StatsPullAtomCallbackImpl implements StatsManager.StatsPullAtomCallback {
        @Override
        public int onPullAtom(int atomTag, List<StatsEvent> data) {
            switch (atomTag) {
                case FrameworkStatsLog.BLOB_INFO:
                    return pullBlobData(atomTag, data);
                default:
                    throw new UnsupportedOperationException("Unknown tagId=" + atomTag);
            }
        }
    }

    private int pullBlobData(int atomTag, List<StatsEvent> data) {
        synchronized (mBlobsLock) {
            for (int i = 0, userCount = mBlobsMap.size(); i < userCount; ++i) {
                final ArrayMap<BlobHandle, BlobMetadata> userBlobs = mBlobsMap.valueAt(i);
                for (int j = 0, blobsCount = userBlobs.size(); j < blobsCount; ++j) {
                    final BlobMetadata blob = userBlobs.valueAt(j);
                    data.add(blob.dumpAsStatsEvent(atomTag));
                }
            }
        }
        return StatsManager.PULL_SUCCESS;
    }

    private class LocalService extends BlobStoreManagerInternal {
        @Override
        public void onIdleMaintenance() {
+55 −32
Original line number Diff line number Diff line
@@ -53,12 +53,15 @@ import android.util.Slog;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.FrameworkStatsLog;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.Preconditions;
import com.android.internal.util.XmlUtils;
import com.android.server.blob.BlobStoreManagerService.DumpArgs;
import com.android.server.blob.BlobStoreManagerService.SessionStateChangeListener;

import libcore.io.IoUtils;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;
@@ -207,27 +210,37 @@ class BlobStoreSession extends IBlobStoreSession.Stub {
                throw new IllegalStateException("Not allowed to write in state: "
                        + stateToString(mState));
            }
        }

        FileDescriptor fd = null;
        try {
                return openWriteLocked(offsetBytes, lengthBytes);
            fd = openWriteInternal(offsetBytes, lengthBytes);
            final RevocableFileDescriptor revocableFd = new RevocableFileDescriptor(mContext, fd);
            synchronized (mSessionLock) {
                if (mState != STATE_OPENED) {
                    IoUtils.closeQuietly(fd);
                    throw new IllegalStateException("Not allowed to write in state: "
                            + stateToString(mState));
                }
                trackRevocableFdLocked(revocableFd);
                return revocableFd.getRevocableFileDescriptor();
            }
        } catch (IOException e) {
            IoUtils.closeQuietly(fd);
            throw ExceptionUtils.wrap(e);
        }
    }
    }

    @GuardedBy("mSessionLock")
    @NonNull
    private ParcelFileDescriptor openWriteLocked(@BytesLong long offsetBytes,
    private FileDescriptor openWriteInternal(@BytesLong long offsetBytes,
            @BytesLong long lengthBytes) throws IOException {
        // TODO: Add limit on active open sessions/writes/reads
        FileDescriptor fd = null;
        try {
            final File sessionFile = getSessionFile();
            if (sessionFile == null) {
                throw new IllegalStateException("Couldn't get the file for this session");
            }
            fd = Os.open(sessionFile.getPath(), O_CREAT | O_RDWR, 0600);
            final FileDescriptor fd = Os.open(sessionFile.getPath(), O_CREAT | O_RDWR, 0600);
            if (offsetBytes > 0) {
                final long curOffset = Os.lseek(fd, offsetBytes, SEEK_SET);
                if (curOffset != offsetBytes) {
@@ -238,10 +251,10 @@ class BlobStoreSession extends IBlobStoreSession.Stub {
            if (lengthBytes > 0) {
                mContext.getSystemService(StorageManager.class).allocateBytes(fd, lengthBytes);
            }
            return fd;
        } catch (ErrnoException e) {
            e.rethrowAsIOException();
            throw e.rethrowAsIOException();
        }
        return createRevocableFdLocked(fd);
    }

    @Override
@@ -253,29 +266,40 @@ class BlobStoreSession extends IBlobStoreSession.Stub {
                throw new IllegalStateException("Not allowed to read in state: "
                        + stateToString(mState));
            }
        }

        FileDescriptor fd = null;
        try {
                return openReadLocked();
            fd = openReadInternal();
            final RevocableFileDescriptor revocableFd = new RevocableFileDescriptor(mContext, fd);
            synchronized (mSessionLock) {
                if (mState != STATE_OPENED) {
                    IoUtils.closeQuietly(fd);
                    throw new IllegalStateException("Not allowed to read in state: "
                            + stateToString(mState));
                }
                trackRevocableFdLocked(revocableFd);
                return revocableFd.getRevocableFileDescriptor();
            }

        } catch (IOException e) {
            IoUtils.closeQuietly(fd);
            throw ExceptionUtils.wrap(e);
        }
    }
    }

    @GuardedBy("mSessionLock")
    @NonNull
    private ParcelFileDescriptor openReadLocked() throws IOException {
        FileDescriptor fd = null;
    private FileDescriptor openReadInternal() throws IOException {
        try {
            final File sessionFile = getSessionFile();
            if (sessionFile == null) {
                throw new IllegalStateException("Couldn't get the file for this session");
            }
            fd = Os.open(sessionFile.getPath(), O_RDONLY, 0);
            final FileDescriptor fd = Os.open(sessionFile.getPath(), O_RDONLY, 0);
            return fd;
        } catch (ErrnoException e) {
            e.rethrowAsIOException();
            throw e.rethrowAsIOException();
        }
        return createRevocableFdLocked(fd);
    }

    @Override
@@ -396,7 +420,7 @@ class BlobStoreSession extends IBlobStoreSession.Stub {
            }

            mState = state;
            revokeAllFdsLocked();
            revokeAllFds();

            if (sendCallback) {
                mListener.onStateChanged(this);
@@ -427,26 +451,26 @@ class BlobStoreSession extends IBlobStoreSession.Stub {
                        + ") didn't match the given BlobHandle.digest ("
                        + BlobHandle.safeDigest(mBlobHandle.digest) + ")");
                mState = STATE_VERIFIED_INVALID;

                FrameworkStatsLog.write(FrameworkStatsLog.BLOB_COMMITTED, getOwnerUid(), mSessionId,
                        getSize(), FrameworkStatsLog.BLOB_COMMITTED__RESULT__DIGEST_MISMATCH);
                sendCommitCallbackResult(COMMIT_RESULT_ERROR);
            }
            mListener.onStateChanged(this);
        }
    }

    @GuardedBy("mSessionLock")
    private void revokeAllFdsLocked() {
    private void revokeAllFds() {
        synchronized (mRevocableFds) {
            for (int i = mRevocableFds.size() - 1; i >= 0; --i) {
                mRevocableFds.get(i).revoke();
            }
            mRevocableFds.clear();
        }
    }

    @GuardedBy("mSessionLock")
    @NonNull
    private ParcelFileDescriptor createRevocableFdLocked(FileDescriptor fd)
            throws IOException {
        final RevocableFileDescriptor revocableFd =
                new RevocableFileDescriptor(mContext, fd);
    private void trackRevocableFdLocked(RevocableFileDescriptor revocableFd) {
        synchronized (mRevocableFds) {
            mRevocableFds.add(revocableFd);
        }
@@ -455,7 +479,6 @@ class BlobStoreSession extends IBlobStoreSession.Stub {
                mRevocableFds.remove(revocableFd);
            }
        });
        return revocableFd.getRevocableFileDescriptor();
    }

    @Nullable
Loading