package com.android.mtp;
import android.content.Context;
import android.mtp.MtpObjectInfo;
import android.os.ParcelFileDescriptor;
import android.system.ErrnoException;
import android.system.Os;
import android.system.OsConstants;
import com.android.internal.util.Preconditions;
import java.io.File;
import java.io.IOException;
class MtpFileWriter implements AutoCloseable {
final ParcelFileDescriptor mCacheFd;
final String mDocumentId;
boolean mDirty;
MtpFileWriter(Context context, String documentId) throws IOException {
mDocumentId = documentId;
mDirty = false;
final File tempFile = File.createTempFile("mtp", "tmp", context.getCacheDir());
mCacheFd = ParcelFileDescriptor.open(
tempFile,
ParcelFileDescriptor.MODE_READ_WRITE |
ParcelFileDescriptor.MODE_TRUNCATE |
ParcelFileDescriptor.MODE_CREATE);
tempFile.delete();
}
String getDocumentId() {
return mDocumentId;
}
int write(long offset, int size, byte[] bytes) throws IOException, ErrnoException {
Preconditions.checkArgumentNonnegative(offset, "offset");
Preconditions.checkArgumentNonnegative(size, "size");
Preconditions.checkArgument(size <= bytes.length);
if (size == 0) {
return 0;
}
mDirty = true;
Os.lseek(mCacheFd.getFileDescriptor(), offset, OsConstants.SEEK_SET);
return Os.write(mCacheFd.getFileDescriptor(), bytes, 0, size);
}
void flush(MtpManager manager, MtpDatabase database, int[] operationsSupported)
throws IOException, ErrnoException {
if (!mDirty) {
return;
}
final Identifier identifier = database.createIdentifier(mDocumentId);
final MtpObjectInfo placeholderObjectInfo =
manager.getObjectInfo(identifier.mDeviceId, identifier.mObjectHandle);
manager.deleteDocument(identifier.mDeviceId, identifier.mObjectHandle);
final long size = Os.lseek(mCacheFd.getFileDescriptor(), 0, OsConstants.SEEK_END);
final MtpObjectInfo targetObjectInfo = new MtpObjectInfo.Builder(placeholderObjectInfo)
.setCompressedSize(size)
.build();
Os.lseek(mCacheFd.getFileDescriptor(), 0, OsConstants.SEEK_SET);
final int newObjectHandle = manager.createDocument(
identifier.mDeviceId, targetObjectInfo, mCacheFd);
final MtpObjectInfo newObjectInfo = manager.getObjectInfo(
identifier.mDeviceId, newObjectHandle);
final Identifier parentIdentifier =
database.getParentIdentifier(identifier.mDocumentId);
database.updateObject(
identifier.mDocumentId,
identifier.mDeviceId,
parentIdentifier.mDocumentId,
operationsSupported,
newObjectInfo,
size);
mDirty = false;
}
@Override
public void close() throws IOException {
mCacheFd.close();
}
}