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

Commit 8aa6183e authored by Howard Chen's avatar Howard Chen Committed by Gerrit Code Review
Browse files

Merge "Replace copy-on-write PDB with an empty one"

parents a3e4f953 e11bcc6c
Loading
Loading
Loading
Loading
+41 −82
Original line number Diff line number Diff line
@@ -23,7 +23,6 @@ import android.app.ActivityManager;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Binder;
import android.os.FileUtils;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.SystemProperties;
@@ -45,6 +44,7 @@ import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.security.MessageDigest;
@@ -131,13 +131,13 @@ public class PersistentDataBlockService extends SystemService {
    private static final String FLASH_LOCK_UNLOCKED = "0";

    private final Context mContext;
    private final String mDataBlockFile;
    private final boolean mIsRunningDSU;
    private final Object mLock = new Object();
    private final CountDownLatch mInitDoneSignal = new CountDownLatch(1);

    private int mAllowedUid = -1;
    private long mBlockDeviceSize;
    private String mDataBlockFile;

    @GuardedBy("mLock")
    private boolean mIsWritable = true;
@@ -145,8 +145,12 @@ public class PersistentDataBlockService extends SystemService {
    public PersistentDataBlockService(Context context) {
        super(context);
        mContext = context;
        mDataBlockFile = SystemProperties.get(PERSISTENT_DATA_BLOCK_PROP);
        mIsRunningDSU = SystemProperties.getBoolean(GSI_RUNNING_PROP, false);
        if (mIsRunningDSU) {
            mDataBlockFile = GSI_SANDBOX;
        } else {
            mDataBlockFile = SystemProperties.get(PERSISTENT_DATA_BLOCK_PROP);
        }
        mBlockDeviceSize = -1; // Load lazily
    }

@@ -260,9 +264,13 @@ public class PersistentDataBlockService extends SystemService {
    private long getBlockDeviceSize() {
        synchronized (mLock) {
            if (mBlockDeviceSize == -1) {
                if (mIsRunningDSU) {
                    mBlockDeviceSize = MAX_DATA_BLOCK_SIZE;
                } else {
                    mBlockDeviceSize = nativeGetBlockDeviceSize(mDataBlockFile);
                }
            }
        }

        return mBlockDeviceSize;
    }
@@ -290,40 +298,30 @@ public class PersistentDataBlockService extends SystemService {
        return true;
    }

    private FileOutputStream getBlockOutputStream() throws IOException {
        if (!mIsRunningDSU) {
            return new FileOutputStream(new File(mDataBlockFile));
        } else {
            File sandbox = new File(GSI_SANDBOX);
            File realpdb = new File(SystemProperties.get(PERSISTENT_DATA_BLOCK_PROP));
            if (!sandbox.exists()) {
                FileUtils.copy(realpdb, sandbox);
                mDataBlockFile = GSI_SANDBOX;
            }
            Slog.i(TAG, "PersistentDataBlock copy-on-write");
            return new FileOutputStream(sandbox);
        }
    private FileChannel getBlockOutputChannel() throws IOException {
        return new RandomAccessFile(mDataBlockFile, "rw").getChannel();
    }

    private boolean computeAndWriteDigestLocked() {
        byte[] digest = computeDigestLocked(null);
        if (digest != null) {
            DataOutputStream outputStream;
            FileChannel channel;
            try {
                outputStream = new DataOutputStream(getBlockOutputStream());
                channel = getBlockOutputChannel();
            } catch (IOException e) {
                Slog.e(TAG, "partition not available?", e);
                return false;
            }

            try {
                outputStream.write(digest, 0, DIGEST_SIZE_BYTES);
                outputStream.flush();
                ByteBuffer buf = ByteBuffer.allocate(DIGEST_SIZE_BYTES);
                buf.put(digest);
                buf.flip();
                channel.write(buf);
                channel.force(true);
            } catch (IOException e) {
                Slog.e(TAG, "failed to write block checksum", e);
                return false;
            } finally {
                IoUtils.closeQuietly(outputStream);
            }
            return true;
        } else {
@@ -374,25 +372,18 @@ public class PersistentDataBlockService extends SystemService {
    }

    private void formatPartitionLocked(boolean setOemUnlockEnabled) {
        DataOutputStream outputStream;
        try {
            outputStream = new DataOutputStream(getBlockOutputStream());
        } catch (IOException e) {
            Slog.e(TAG, "partition not available?", e);
            return;
        }

        byte[] data = new byte[DIGEST_SIZE_BYTES];
        try {
            outputStream.write(data, 0, DIGEST_SIZE_BYTES);
            outputStream.writeInt(PARTITION_TYPE_MARKER);
            outputStream.writeInt(0); // data size
            outputStream.flush();
            FileChannel channel = getBlockOutputChannel();
            ByteBuffer buf = ByteBuffer.allocate(DIGEST_SIZE_BYTES + HEADER_SIZE);
            buf.put(new byte[DIGEST_SIZE_BYTES]);
            buf.putInt(PARTITION_TYPE_MARKER);
            buf.putInt(0);
            channel.write(buf);
            channel.force(true);
        } catch (IOException e) {
            Slog.e(TAG, "failed to format block", e);
            return;
        } finally {
            IoUtils.closeQuietly(outputStream);
        }

        doSetOemUnlockEnabledLocked(setOemUnlockEnabled);
@@ -400,16 +391,9 @@ public class PersistentDataBlockService extends SystemService {
    }

    private void doSetOemUnlockEnabledLocked(boolean enabled) {
        FileOutputStream outputStream;
        try {
            outputStream = getBlockOutputStream();
        } catch (IOException e) {
            Slog.e(TAG, "partition not available", e);
            return;
        }

        try {
            FileChannel channel = outputStream.getChannel();
            FileChannel channel = getBlockOutputChannel();

            channel.position(getBlockDeviceSize() - 1);

@@ -417,13 +401,12 @@ public class PersistentDataBlockService extends SystemService {
            data.put(enabled ? (byte) 1 : (byte) 0);
            data.flip();
            channel.write(data);
            outputStream.flush();
            channel.force(true);
        } catch (IOException e) {
            Slog.e(TAG, "unable to access persistent partition", e);
            return;
        } finally {
            SystemProperties.set(OEM_UNLOCK_PROP, enabled ? "1" : "0");
            IoUtils.closeQuietly(outputStream);
        }
    }

@@ -477,35 +460,32 @@ public class PersistentDataBlockService extends SystemService {
                return (int) -maxBlockSize;
            }

            DataOutputStream outputStream;
            FileChannel channel;
            try {
                outputStream = new DataOutputStream(getBlockOutputStream());
                channel = getBlockOutputChannel();
            } catch (IOException e) {
                Slog.e(TAG, "partition not available?", e);
               return -1;
            }

            ByteBuffer headerAndData = ByteBuffer.allocate(data.length + HEADER_SIZE);
            ByteBuffer headerAndData = ByteBuffer.allocate(
                                           data.length + HEADER_SIZE + DIGEST_SIZE_BYTES);
            headerAndData.put(new byte[DIGEST_SIZE_BYTES]);
            headerAndData.putInt(PARTITION_TYPE_MARKER);
            headerAndData.putInt(data.length);
            headerAndData.put(data);

            headerAndData.flip();
            synchronized (mLock) {
                if (!mIsWritable) {
                    IoUtils.closeQuietly(outputStream);
                    return -1;
                }

                try {
                    byte[] checksum = new byte[DIGEST_SIZE_BYTES];
                    outputStream.write(checksum, 0, DIGEST_SIZE_BYTES);
                    outputStream.write(headerAndData.array());
                    outputStream.flush();
                    channel.write(headerAndData);
                    channel.force(true);
                } catch (IOException e) {
                    Slog.e(TAG, "failed writing to the persistent data block", e);
                    return -1;
                } finally {
                    IoUtils.closeQuietly(outputStream);
                }

                if (computeAndWriteDigestLocked()) {
@@ -565,17 +545,6 @@ public class PersistentDataBlockService extends SystemService {
        public void wipe() {
            enforceOemUnlockWritePermission();

            if (mIsRunningDSU) {
                File sandbox = new File(GSI_SANDBOX);
                if (sandbox.exists()) {
                    if (sandbox.delete()) {
                        mDataBlockFile = SystemProperties.get(PERSISTENT_DATA_BLOCK_PROP);
                    } else {
                        Slog.e(TAG, "Failed to wipe sandbox persistent data block");
                    }
                }
                return;
            }
            synchronized (mLock) {
                int ret = nativeWipe(mDataBlockFile);

@@ -733,28 +702,18 @@ public class PersistentDataBlockService extends SystemService {
        }

        private void writeDataBuffer(long offset, ByteBuffer dataBuffer) {
            FileOutputStream outputStream;
            try {
                outputStream = getBlockOutputStream();
            } catch (IOException e) {
                Slog.e(TAG, "partition not available", e);
                return;
            }
            synchronized (mLock) {
                if (!mIsWritable) {
                    IoUtils.closeQuietly(outputStream);
                    return;
                }
                try {
                    FileChannel channel = outputStream.getChannel();
                    FileChannel channel = getBlockOutputChannel();
                    channel.position(offset);
                    channel.write(dataBuffer);
                    outputStream.flush();
                    channel.force(true);
                } catch (IOException e) {
                    Slog.e(TAG, "unable to access persistent partition", e);
                    return;
                } finally {
                    IoUtils.closeQuietly(outputStream);
                }

                computeAndWriteDigestLocked();