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

Commit 755f7268 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Move chunk proto definitions into the BackupEncrypter APK"

parents 1d35b3cd 572df9ff
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -15,8 +15,10 @@
 */

syntax = "proto2";
package com.android.server.backup.encryption.chunk;

package android_backup_crypto;

option java_package = "com.android.server.backup.encryption.protos";
option java_outer_classname = "ChunksMetadataProto";

// Cipher type with which the chunks are encrypted. For now we only support AES/GCM/NoPadding, but
+0 −70
Original line number Diff line number Diff line
/*
 * Copyright (C) 2018 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.backup.encryption.chunk;

import android.util.proto.ProtoInputStream;

import java.io.IOException;

/**
 * Information about a chunk entry in a protobuf. Only used for reading from a {@link
 * ProtoInputStream}.
 */
public class Chunk {
    /**
     * Reads a Chunk from a {@link ProtoInputStream}. Expects the message to be of format {@link
     * ChunksMetadataProto.Chunk}.
     *
     * @param inputStream currently at a {@link ChunksMetadataProto.Chunk} message.
     * @throws IOException when the message is not structured as expected or a field can not be
     *     read.
     */
    static Chunk readFromProto(ProtoInputStream inputStream) throws IOException {
        Chunk result = new Chunk();

        while (inputStream.nextField() != ProtoInputStream.NO_MORE_FIELDS) {
            switch (inputStream.getFieldNumber()) {
                case (int) ChunksMetadataProto.Chunk.HASH:
                    result.mHash = inputStream.readBytes(ChunksMetadataProto.Chunk.HASH);
                    break;
                case (int) ChunksMetadataProto.Chunk.LENGTH:
                    result.mLength = inputStream.readInt(ChunksMetadataProto.Chunk.LENGTH);
                    break;
            }
        }

        return result;
    }

    private int mLength;
    private byte[] mHash;

    /** Private constructor. This class should only be instantiated by calling readFromProto. */
    private Chunk() {
        // Set default values for fields in case they are not available in the proto.
        mHash = new byte[]{};
        mLength = 0;
    }

    public int getLength() {
        return mLength;
    }

    public byte[] getHash() {
        return mHash;
    }
}
+0 −109
Original line number Diff line number Diff line
/*
 * Copyright (C) 2019 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.backup.encryption.chunk;

import android.annotation.Nullable;
import android.util.proto.ProtoInputStream;

import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

/**
 * Chunk listing in a format optimized for quick look-up of chunks via their hash keys. This is
 * useful when building an incremental backup. After a chunk has been produced, the algorithm can
 * quickly look up whether the chunk existed in the previous backup by checking this chunk listing.
 * It can then tell the server to use that chunk, through telling it the position and length of the
 * chunk in the previous backup's blob.
 */
public class ChunkListingMap {
    /**
     * Reads a ChunkListingMap from a {@link ProtoInputStream}. Expects the message to be of format
     * {@link ChunksMetadataProto.ChunkListing}.
     *
     * @param inputStream Currently at a {@link ChunksMetadataProto.ChunkListing} message.
     * @throws IOException when the message is not structured as expected or a field can not be
     *     read.
     */
    public static ChunkListingMap readFromProto(ProtoInputStream inputStream) throws IOException {
        Map<ChunkHash, Entry> entries = new HashMap();

        long start = 0;

        while (inputStream.nextField() != ProtoInputStream.NO_MORE_FIELDS) {
            if (inputStream.getFieldNumber() == (int) ChunksMetadataProto.ChunkListing.CHUNKS) {
                long chunkToken = inputStream.start(ChunksMetadataProto.ChunkListing.CHUNKS);
                Chunk chunk = Chunk.readFromProto(inputStream);
                entries.put(new ChunkHash(chunk.getHash()), new Entry(start, chunk.getLength()));
                start += chunk.getLength();
                inputStream.end(chunkToken);
            }
        }

        return new ChunkListingMap(entries);
    }

    private final Map<ChunkHash, Entry> mChunksByHash;

    private ChunkListingMap(Map<ChunkHash, Entry> chunksByHash) {
        mChunksByHash = Collections.unmodifiableMap(new HashMap<>(chunksByHash));
    }

    /** Returns {@code true} if there is a chunk with the given SHA-256 MAC key in the listing. */
    public boolean hasChunk(ChunkHash hash) {
        return mChunksByHash.containsKey(hash);
    }

    /**
     * Returns the entry for the chunk with the given hash.
     *
     * @param hash The SHA-256 MAC of the plaintext of the chunk.
     * @return The entry, containing position and length of the chunk in the backup blob, or null if
     *     it does not exist.
     */
    @Nullable
    public Entry getChunkEntry(ChunkHash hash) {
        return mChunksByHash.get(hash);
    }

    /** Returns the number of chunks in this listing. */
    public int getChunkCount() {
        return mChunksByHash.size();
    }

    /** Information about a chunk entry in a backup blob - i.e., its position and length. */
    public static final class Entry {
        private final int mLength;
        private final long mStart;

        private Entry(long start, int length) {
            mStart = start;
            mLength = length;
        }

        /** Returns the length of the chunk in bytes. */
        public int getLength() {
            return mLength;
        }

        /** Returns the start position of the chunk in the backup blob, in bytes. */
        public long getStart() {
            return mStart;
        }
    }
}
+3 −3
Original line number Diff line number Diff line
@@ -16,9 +16,9 @@

package com.android.server.backup.encryption.chunk;

import static com.android.server.backup.encryption.chunk.ChunksMetadataProto.CHUNK_ORDERING_TYPE_UNSPECIFIED;
import static com.android.server.backup.encryption.chunk.ChunksMetadataProto.EXPLICIT_STARTS;
import static com.android.server.backup.encryption.chunk.ChunksMetadataProto.INLINE_LENGTHS;
import static com.android.server.backup.encryption.protos.nano.ChunksMetadataProto.CHUNK_ORDERING_TYPE_UNSPECIFIED;
import static com.android.server.backup.encryption.protos.nano.ChunksMetadataProto.EXPLICIT_STARTS;
import static com.android.server.backup.encryption.protos.nano.ChunksMetadataProto.INLINE_LENGTHS;

import android.annotation.IntDef;

+1 −1
Original line number Diff line number Diff line
@@ -17,7 +17,7 @@
package com.android.server.backup.encryption.chunking;

import com.android.server.backup.encryption.chunk.ChunkOrderingType;
import com.android.server.backup.encryption.chunk.ChunksMetadataProto;
import com.android.server.backup.encryption.protos.nano.ChunksMetadataProto;

import java.io.IOException;

Loading