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

Commit ae53d116 authored by Sudheer Shanka's avatar Sudheer Shanka
Browse files

Schedule a maintenance job to clean up stale jobs.

+ Fix a bug in BlobMetadata.hasLeases().

Bug: 148754858
Test: atest ./services/tests/mockingservicestests/src/com/android/server/blob/BlobStoreManagerServiceTest.java
Test: adb shell cmd jobscheduler run --force android 191934935
Change-Id: I13499dd0327414bee62b8395c7e1fd349e325dd4
parent 981f524a
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -4,7 +4,7 @@
      "name": "CtsBlobStoreTestCases"
    },
    {
      "name": "FrameworksServicesTests",
      "name": "FrameworksMockingServicesTests",
      "options": [
        {
          "include-filter": "com.android.server.blob"
+5 −0
Original line number Diff line number Diff line
@@ -257,6 +257,11 @@ public final class BlobHandle implements Parcelable {
        return Base64.encodeToString(digest, Base64.NO_WRAP);
    }

    /** @hide */
    public boolean isExpired() {
        return expiryTimeMillis != 0 && expiryTimeMillis < System.currentTimeMillis();
    }

    public static final @NonNull Creator<BlobHandle> CREATOR = new Creator<BlobHandle>() {
        @Override
        public @NonNull BlobHandle createFromParcel(@NonNull Parcel source) {
+24 −12
Original line number Diff line number Diff line
@@ -64,9 +64,9 @@ class BlobMetadata {

    private final Context mContext;

    public final long blobId;
    public final BlobHandle blobHandle;
    public final int userId;
    private final long mBlobId;
    private final BlobHandle mBlobHandle;
    private final int mUserId;

    @GuardedBy("mMetadataLock")
    private final ArraySet<Committer> mCommitters = new ArraySet<>();
@@ -90,9 +90,21 @@ class BlobMetadata {

    BlobMetadata(Context context, long blobId, BlobHandle blobHandle, int userId) {
        mContext = context;
        this.blobId = blobId;
        this.blobHandle = blobHandle;
        this.userId = userId;
        this.mBlobId = blobId;
        this.mBlobHandle = blobHandle;
        this.mUserId = userId;
    }

    long getBlobId() {
        return mBlobId;
    }

    BlobHandle getBlobHandle() {
        return mBlobHandle;
    }

    int getUserId() {
        return mUserId;
    }

    void addCommitter(@NonNull Committer committer) {
@@ -159,7 +171,7 @@ class BlobMetadata {

    boolean hasLeases() {
        synchronized (mMetadataLock) {
            return mLeasees.isEmpty();
            return !mLeasees.isEmpty();
        }
    }

@@ -196,7 +208,7 @@ class BlobMetadata {

    File getBlobFile() {
        if (mBlobFile == null) {
            mBlobFile = BlobStoreConfig.getBlobFile(blobId);
            mBlobFile = BlobStoreConfig.getBlobFile(mBlobId);
        }
        return mBlobFile;
    }
@@ -244,7 +256,7 @@ class BlobMetadata {
    void dump(IndentingPrintWriter fout, DumpArgs dumpArgs) {
        fout.println("blobHandle:");
        fout.increaseIndent();
        blobHandle.dump(fout, dumpArgs.shouldDumpFull());
        mBlobHandle.dump(fout, dumpArgs.shouldDumpFull());
        fout.decreaseIndent();

        fout.println("Committers:");
@@ -274,11 +286,11 @@ class BlobMetadata {

    void writeToXml(XmlSerializer out) throws IOException {
        synchronized (mMetadataLock) {
            XmlUtils.writeLongAttribute(out, ATTR_ID, blobId);
            XmlUtils.writeIntAttribute(out, ATTR_USER_ID, userId);
            XmlUtils.writeLongAttribute(out, ATTR_ID, mBlobId);
            XmlUtils.writeIntAttribute(out, ATTR_USER_ID, mUserId);

            out.startTag(null, TAG_BLOB_HANDLE);
            blobHandle.writeToXml(out);
            mBlobHandle.writeToXml(out);
            out.endTag(null, TAG_BLOB_HANDLE);

            for (int i = 0, count = mCommitters.size(); i < count; ++i) {
+15 −0
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import android.os.Environment;
import android.util.Slog;

import java.io.File;
import java.util.concurrent.TimeUnit;

class BlobStoreConfig {
    public static final String TAG = "BlobStore";
@@ -32,6 +33,20 @@ class BlobStoreConfig {
    private static final String SESSIONS_INDEX_FILE_NAME = "sessions_index.xml";
    private static final String BLOBS_INDEX_FILE_NAME = "blobs_index.xml";

    /**
     * Job Id for idle maintenance job ({@link BlobStoreIdleJobService}).
     */
    public static final int IDLE_JOB_ID = 0xB70B1D7; // 191934935L
    /**
     * Max time period (in millis) between each idle maintenance job run.
     */
    public static final long IDLE_JOB_PERIOD_MILLIS = TimeUnit.DAYS.toMillis(1);

    /**
     * Timeout in millis after which sessions with no updates will be deleted.
     */
    public static final long SESSION_EXPIRY_TIMEOUT_MILLIS = TimeUnit.DAYS.toMillis(7);

    @Nullable
    public static File prepareBlobFile(long sessionId) {
        final File blobsDir = prepareBlobsDir();
+62 −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 com.android.server.blob;

import static com.android.server.blob.BlobStoreConfig.IDLE_JOB_ID;
import static com.android.server.blob.BlobStoreConfig.IDLE_JOB_PERIOD_MILLIS;

import android.app.job.JobInfo;
import android.app.job.JobParameters;
import android.app.job.JobScheduler;
import android.app.job.JobService;
import android.content.ComponentName;
import android.content.Context;
import android.os.AsyncTask;

import com.android.server.LocalServices;

/**
 * Maintenance job to clean up stale sessions and blobs.
 */
public class BlobStoreIdleJobService extends JobService {
    @Override
    public boolean onStartJob(final JobParameters params) {
        AsyncTask.execute(() -> {
            final BlobStoreManagerInternal blobStoreManagerInternal = LocalServices.getService(
                    BlobStoreManagerInternal.class);
            blobStoreManagerInternal.onIdleMaintenance();
            jobFinished(params, false);
        });
        return false;
    }

    @Override
    public boolean onStopJob(final JobParameters params) {
        return false;
    }

    static void schedule(Context context) {
        final JobScheduler jobScheduler = (JobScheduler) context.getSystemService(
                Context.JOB_SCHEDULER_SERVICE);
        final JobInfo job = new JobInfo.Builder(IDLE_JOB_ID,
                new ComponentName(context, BlobStoreIdleJobService.class))
                        .setRequiresDeviceIdle(true)
                        .setRequiresCharging(true)
                        .setPeriodic(IDLE_JOB_PERIOD_MILLIS)
                        .build();
        jobScheduler.schedule(job);
    }
}
Loading