blob: 79de0d19f5a3139035a34a1e421e65a4c20e7399 [file]
/*
* 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.cts.releaseparser;
import com.android.cts.releaseparser.ReleaseProto.*;
import java.io.File;
import java.io.RandomAccessFile;
import java.util.Arrays;
import java.util.logging.Logger;
// ART file format at art/runtime/image.h
public class ArtParser extends FileParser {
// The magic values for the ART identification.
private static final byte[] ART_MAGIC = {(byte) 'a', (byte) 'r', (byte) 't', (byte) 0x0A};
private static final int HEADER_SIZE = 512;
private ArtInfo.Builder mArtInfoBuilder;
public ArtParser(File file) {
super(file);
}
@Override
public Entry.EntryType getType() {
return Entry.EntryType.ART;
}
@Override
public void setAdditionalInfo() {
getFileEntryBuilder().setArtInfo(getArtInfo());
}
@Override
public String getCodeId() {
if (mArtInfoBuilder == null) {
parse();
}
return mCodeId;
}
public ArtInfo getArtInfo() {
if (mArtInfoBuilder == null) {
parse();
}
return mArtInfoBuilder.build();
}
private void parse() {
byte[] buffer = new byte[HEADER_SIZE];
mArtInfoBuilder = ArtInfo.newBuilder();
// ToDo check this
int kSectionCount = 11;
int kImageMethodsCount = 20;
try {
RandomAccessFile raFile = new RandomAccessFile(getFile(), "r");
raFile.seek(0);
raFile.readFully(buffer, 0, HEADER_SIZE);
raFile.close();
if (buffer[0] != ART_MAGIC[0]
|| buffer[1] != ART_MAGIC[1]
|| buffer[2] != ART_MAGIC[2]
|| buffer[3] != ART_MAGIC[3]) {
String content = new String(buffer);
System.err.println("Invalid ART file:" + getFileName() + " " + content);
mArtInfoBuilder.setValid(false);
return;
}
int offset = 4;
mArtInfoBuilder.setVersion(new String(Arrays.copyOfRange(buffer, offset, offset + 4)));
offset += 4;
mArtInfoBuilder.setImageBegin(getIntLittleEndian(buffer, offset));
offset += 4;
mArtInfoBuilder.setImageSize(getIntLittleEndian(buffer, offset));
offset += 4;
int oatChecksum = getIntLittleEndian(buffer, offset);
offset += 4;
mArtInfoBuilder.setOatChecksum(oatChecksum);
mCodeId = String.format(CODE_ID_FORMAT, oatChecksum);
mArtInfoBuilder.setOatFileBegin(getIntLittleEndian(buffer, offset));
offset += 4;
mArtInfoBuilder.setOatDataBegin(getIntLittleEndian(buffer, offset));
offset += 4;
mArtInfoBuilder.setOatDataEnd(getIntLittleEndian(buffer, offset));
offset += 4;
mArtInfoBuilder.setOatFileEnd(getIntLittleEndian(buffer, offset));
offset += 4;
mArtInfoBuilder.setBootImageBegin(getIntLittleEndian(buffer, offset));
offset += 4;
mArtInfoBuilder.setBootImageSize(getIntLittleEndian(buffer, offset));
offset += 4;
mArtInfoBuilder.setBootOatBegin(getIntLittleEndian(buffer, offset));
offset += 4;
mArtInfoBuilder.setBootOatSize(getIntLittleEndian(buffer, offset));
offset += 4;
mArtInfoBuilder.setPatchDelta(getIntLittleEndian(buffer, offset));
offset += 4;
mArtInfoBuilder.setImageRoots(getIntLittleEndian(buffer, offset));
offset += 4;
mArtInfoBuilder.setPointerSize(getIntLittleEndian(buffer, offset));
offset += 4;
mArtInfoBuilder.setCompilePic(getIntLittleEndian(buffer, offset));
offset += 4;
// Todo check further
mArtInfoBuilder.setIsPic(getIntLittleEndian(buffer, offset));
offset += 4;
mArtInfoBuilder.setStorageMode(getIntLittleEndian(buffer, offset));
offset += 4;
mArtInfoBuilder.setDataSize(getIntLittleEndian(buffer, offset));
mArtInfoBuilder.setValid(true);
} catch (Exception ex) {
System.err.println("Invalid ART file:" + getFileName());
mArtInfoBuilder.setValid(false);
}
}
private static final String USAGE_MESSAGE =
"Usage: java -jar releaseparser.jar "
+ ArtParser.class.getCanonicalName()
+ " [-options <parameter>]...\n"
+ " to parse APK file meta data\n"
+ "Options:\n"
+ "\t-i PATH\t The file path of the file to be parsed.\n"
+ "\t-of PATH\t The file path of the output file instead of printing to System.out.\n";
public static void main(String[] args) {
try {
ArgumentParser argParser = new ArgumentParser(args);
String fileName = argParser.getParameterElement("i", 0);
String outputFileName = argParser.getParameterElement("of", 0);
File aFile = new File(fileName);
ArtParser aParser = new ArtParser(aFile);
Entry fileEntry = aParser.getFileEntryBuilder().build();
writeTextFormatMessage(outputFileName, fileEntry);
} catch (Exception ex) {
System.out.println(USAGE_MESSAGE);
ex.printStackTrace();
}
}
private static Logger getLogger() {
return Logger.getLogger(ArtParser.class.getSimpleName());
}
}