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

This commit is contained in:
Howard Chen
2021-04-07 15:21:00 +00:00
committed by Gerrit Code Review

View File

@@ -23,7 +23,6 @@ import android.app.ActivityManager;
import android.content.Context; import android.content.Context;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.os.Binder; import android.os.Binder;
import android.os.FileUtils;
import android.os.IBinder; import android.os.IBinder;
import android.os.RemoteException; import android.os.RemoteException;
import android.os.SystemProperties; import android.os.SystemProperties;
@@ -45,6 +44,7 @@ import java.io.FileInputStream;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.channels.FileChannel; import java.nio.channels.FileChannel;
import java.security.MessageDigest; import java.security.MessageDigest;
@@ -131,13 +131,13 @@ public class PersistentDataBlockService extends SystemService {
private static final String FLASH_LOCK_UNLOCKED = "0"; private static final String FLASH_LOCK_UNLOCKED = "0";
private final Context mContext; private final Context mContext;
private final String mDataBlockFile;
private final boolean mIsRunningDSU; private final boolean mIsRunningDSU;
private final Object mLock = new Object(); private final Object mLock = new Object();
private final CountDownLatch mInitDoneSignal = new CountDownLatch(1); private final CountDownLatch mInitDoneSignal = new CountDownLatch(1);
private int mAllowedUid = -1; private int mAllowedUid = -1;
private long mBlockDeviceSize; private long mBlockDeviceSize;
private String mDataBlockFile;
@GuardedBy("mLock") @GuardedBy("mLock")
private boolean mIsWritable = true; private boolean mIsWritable = true;
@@ -145,8 +145,12 @@ public class PersistentDataBlockService extends SystemService {
public PersistentDataBlockService(Context context) { public PersistentDataBlockService(Context context) {
super(context); super(context);
mContext = context; mContext = context;
mDataBlockFile = SystemProperties.get(PERSISTENT_DATA_BLOCK_PROP);
mIsRunningDSU = SystemProperties.getBoolean(GSI_RUNNING_PROP, false); mIsRunningDSU = SystemProperties.getBoolean(GSI_RUNNING_PROP, false);
if (mIsRunningDSU) {
mDataBlockFile = GSI_SANDBOX;
} else {
mDataBlockFile = SystemProperties.get(PERSISTENT_DATA_BLOCK_PROP);
}
mBlockDeviceSize = -1; // Load lazily mBlockDeviceSize = -1; // Load lazily
} }
@@ -260,7 +264,11 @@ public class PersistentDataBlockService extends SystemService {
private long getBlockDeviceSize() { private long getBlockDeviceSize() {
synchronized (mLock) { synchronized (mLock) {
if (mBlockDeviceSize == -1) { if (mBlockDeviceSize == -1) {
mBlockDeviceSize = nativeGetBlockDeviceSize(mDataBlockFile); if (mIsRunningDSU) {
mBlockDeviceSize = MAX_DATA_BLOCK_SIZE;
} else {
mBlockDeviceSize = nativeGetBlockDeviceSize(mDataBlockFile);
}
} }
} }
@@ -290,40 +298,30 @@ public class PersistentDataBlockService extends SystemService {
return true; return true;
} }
private FileOutputStream getBlockOutputStream() throws IOException { private FileChannel getBlockOutputChannel() throws IOException {
if (!mIsRunningDSU) { return new RandomAccessFile(mDataBlockFile, "rw").getChannel();
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 boolean computeAndWriteDigestLocked() { private boolean computeAndWriteDigestLocked() {
byte[] digest = computeDigestLocked(null); byte[] digest = computeDigestLocked(null);
if (digest != null) { if (digest != null) {
DataOutputStream outputStream; FileChannel channel;
try { try {
outputStream = new DataOutputStream(getBlockOutputStream()); channel = getBlockOutputChannel();
} catch (IOException e) { } catch (IOException e) {
Slog.e(TAG, "partition not available?", e); Slog.e(TAG, "partition not available?", e);
return false; return false;
} }
try { try {
outputStream.write(digest, 0, DIGEST_SIZE_BYTES); ByteBuffer buf = ByteBuffer.allocate(DIGEST_SIZE_BYTES);
outputStream.flush(); buf.put(digest);
buf.flip();
channel.write(buf);
channel.force(true);
} catch (IOException e) { } catch (IOException e) {
Slog.e(TAG, "failed to write block checksum", e); Slog.e(TAG, "failed to write block checksum", e);
return false; return false;
} finally {
IoUtils.closeQuietly(outputStream);
} }
return true; return true;
} else { } else {
@@ -374,25 +372,18 @@ public class PersistentDataBlockService extends SystemService {
} }
private void formatPartitionLocked(boolean setOemUnlockEnabled) { 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 { try {
outputStream.write(data, 0, DIGEST_SIZE_BYTES); FileChannel channel = getBlockOutputChannel();
outputStream.writeInt(PARTITION_TYPE_MARKER); ByteBuffer buf = ByteBuffer.allocate(DIGEST_SIZE_BYTES + HEADER_SIZE);
outputStream.writeInt(0); // data size buf.put(new byte[DIGEST_SIZE_BYTES]);
outputStream.flush(); buf.putInt(PARTITION_TYPE_MARKER);
buf.putInt(0);
channel.write(buf);
channel.force(true);
} catch (IOException e) { } catch (IOException e) {
Slog.e(TAG, "failed to format block", e); Slog.e(TAG, "failed to format block", e);
return; return;
} finally {
IoUtils.closeQuietly(outputStream);
} }
doSetOemUnlockEnabledLocked(setOemUnlockEnabled); doSetOemUnlockEnabledLocked(setOemUnlockEnabled);
@@ -400,16 +391,9 @@ public class PersistentDataBlockService extends SystemService {
} }
private void doSetOemUnlockEnabledLocked(boolean enabled) { private void doSetOemUnlockEnabledLocked(boolean enabled) {
FileOutputStream outputStream;
try {
outputStream = getBlockOutputStream();
} catch (IOException e) {
Slog.e(TAG, "partition not available", e);
return;
}
try { try {
FileChannel channel = outputStream.getChannel(); FileChannel channel = getBlockOutputChannel();
channel.position(getBlockDeviceSize() - 1); channel.position(getBlockDeviceSize() - 1);
@@ -417,13 +401,12 @@ public class PersistentDataBlockService extends SystemService {
data.put(enabled ? (byte) 1 : (byte) 0); data.put(enabled ? (byte) 1 : (byte) 0);
data.flip(); data.flip();
channel.write(data); channel.write(data);
outputStream.flush(); channel.force(true);
} catch (IOException e) { } catch (IOException e) {
Slog.e(TAG, "unable to access persistent partition", e); Slog.e(TAG, "unable to access persistent partition", e);
return; return;
} finally { } finally {
SystemProperties.set(OEM_UNLOCK_PROP, enabled ? "1" : "0"); SystemProperties.set(OEM_UNLOCK_PROP, enabled ? "1" : "0");
IoUtils.closeQuietly(outputStream);
} }
} }
@@ -477,35 +460,32 @@ public class PersistentDataBlockService extends SystemService {
return (int) -maxBlockSize; return (int) -maxBlockSize;
} }
DataOutputStream outputStream; FileChannel channel;
try { try {
outputStream = new DataOutputStream(getBlockOutputStream()); channel = getBlockOutputChannel();
} catch (IOException e) { } catch (IOException e) {
Slog.e(TAG, "partition not available?", e); Slog.e(TAG, "partition not available?", e);
return -1; 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(PARTITION_TYPE_MARKER);
headerAndData.putInt(data.length); headerAndData.putInt(data.length);
headerAndData.put(data); headerAndData.put(data);
headerAndData.flip();
synchronized (mLock) { synchronized (mLock) {
if (!mIsWritable) { if (!mIsWritable) {
IoUtils.closeQuietly(outputStream);
return -1; return -1;
} }
try { try {
byte[] checksum = new byte[DIGEST_SIZE_BYTES]; channel.write(headerAndData);
outputStream.write(checksum, 0, DIGEST_SIZE_BYTES); channel.force(true);
outputStream.write(headerAndData.array());
outputStream.flush();
} catch (IOException e) { } catch (IOException e) {
Slog.e(TAG, "failed writing to the persistent data block", e); Slog.e(TAG, "failed writing to the persistent data block", e);
return -1; return -1;
} finally {
IoUtils.closeQuietly(outputStream);
} }
if (computeAndWriteDigestLocked()) { if (computeAndWriteDigestLocked()) {
@@ -565,17 +545,6 @@ public class PersistentDataBlockService extends SystemService {
public void wipe() { public void wipe() {
enforceOemUnlockWritePermission(); 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) { synchronized (mLock) {
int ret = nativeWipe(mDataBlockFile); int ret = nativeWipe(mDataBlockFile);
@@ -733,28 +702,18 @@ public class PersistentDataBlockService extends SystemService {
} }
private void writeDataBuffer(long offset, ByteBuffer dataBuffer) { 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) { synchronized (mLock) {
if (!mIsWritable) { if (!mIsWritable) {
IoUtils.closeQuietly(outputStream);
return; return;
} }
try { try {
FileChannel channel = outputStream.getChannel(); FileChannel channel = getBlockOutputChannel();
channel.position(offset); channel.position(offset);
channel.write(dataBuffer); channel.write(dataBuffer);
outputStream.flush(); channel.force(true);
} catch (IOException e) { } catch (IOException e) {
Slog.e(TAG, "unable to access persistent partition", e); Slog.e(TAG, "unable to access persistent partition", e);
return; return;
} finally {
IoUtils.closeQuietly(outputStream);
} }
computeAndWriteDigestLocked(); computeAndWriteDigestLocked();