blob: 33c6ea70a6ab0372a5e34e2640ec808810dec880 [file] [log] [blame]
/*
* Copyright (C) 2010 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.tradefed.build;
import com.android.ddmlib.Log;
import com.android.tradefed.util.FileUtil;
import java.io.File;
import java.io.IOException;
import java.util.Hashtable;
import java.util.Map;
/**
* A {@link IBuildInfo} that represents a complete Android device build and (optionally) its tests.
*/
public class DeviceBuildInfo extends BuildInfo implements IDeviceBuildInfo {
private static final String LOG_TAG = "DeviceBuildInfo";
private Map<String, ImageFile> mImageFileMap;
private static final String DEVICE_IMAGE_NAME = "device";
private static final String USERDATA_IMAGE_NAME = "userdata";
private static final String TESTDIR_IMAGE_NAME = "testsdir";
private static final String BASEBAND_IMAGE_NAME = "baseband";
private static final String BOOTLOADER_IMAGE_NAME = "bootloader";
/**
* Data structure containing the image file and related metadata
*/
private static class ImageFile {
private final File mImageFile;
private final String mVersion;
ImageFile(File imageFile, String version) {
mImageFile = imageFile;
mVersion = version;
}
File getImageFile() {
return mImageFile;
}
String getVersion() {
return mVersion;
}
}
public DeviceBuildInfo() {
mImageFileMap = new Hashtable<String, ImageFile>();
}
/**
* Creates a {@link DeviceBuildInfo}.
*
* @param buildId the unique build id
* @param testTarget the test target name
* @param buildName the build name
*/
public DeviceBuildInfo(int buildId, String testTarget, String buildName) {
super(buildId, testTarget, buildName);
mImageFileMap = new Hashtable<String, ImageFile>();
}
/**
* {@inheritDoc}
*/
@Override
public File getImageFile(String imageName) {
ImageFile imgFileRecord = mImageFileMap.get(imageName);
if (imgFileRecord != null) {
return imgFileRecord.getImageFile();
}
return null;
}
/**
* {@inheritDoc}
*/
@Override
public String getImageVersion(String imageName) {
ImageFile imgFileRecord = mImageFileMap.get(imageName);
if (imgFileRecord != null) {
return imgFileRecord.getVersion();
}
return null;
}
/**
* {@inheritDoc}
*/
@Override
public void setImageFile(String imageName, File file, String version) {
if (mImageFileMap.containsKey(imageName)) {
Log.e(LOG_TAG, String.format(
"Device build already contains an image for %s in thread %s", imageName,
Thread.currentThread().getName()));
return;
}
mImageFileMap.put(imageName, new ImageFile(file, version));
}
/**
* {@inheritDoc}
*/
@Override
public File getDeviceImageFile() {
return getImageFile(DEVICE_IMAGE_NAME);
}
/**
* {@inheritDoc}
*/
@Override
public void setDeviceImageFile(File deviceImageFile) {
setImageFile(DEVICE_IMAGE_NAME, deviceImageFile, Integer.toString(getBuildId()));
}
/**
* {@inheritDoc}
*/
@Override
public File getUserDataImageFile() {
return getImageFile(USERDATA_IMAGE_NAME);
}
/**
* {@inheritDoc}
*/
@Override
public void setUserDataImageFile(File userDataFile) {
setImageFile(USERDATA_IMAGE_NAME, userDataFile, Integer.toString(getBuildId()));
}
/**
* {@inheritDoc}
*/
@Override
public File getTestsDir() {
return getImageFile(TESTDIR_IMAGE_NAME);
}
/**
* {@inheritDoc}
*/
@Override
public void setTestsDir(File testsDir) {
setImageFile(TESTDIR_IMAGE_NAME, testsDir, Integer.toString(getBuildId()));
}
/**
* {@inheritDoc}
*/
@Override
public File getBasebandImageFile() {
return getImageFile(BASEBAND_IMAGE_NAME);
}
/**
* {@inheritDoc}
*/
@Override
public String getBasebandVersion() {
return getImageVersion(BASEBAND_IMAGE_NAME);
}
/**
* {@inheritDoc}
*/
@Override
public void setBasebandImage(File basebandFile, String version) {
setImageFile(BASEBAND_IMAGE_NAME, basebandFile, version);
}
/**
* {@inheritDoc}
*/
@Override
public File getBootloaderImageFile() {
return getImageFile(BOOTLOADER_IMAGE_NAME);
}
/**
* {@inheritDoc}
*/
@Override
public String getBootloaderVersion() {
return getImageVersion(BOOTLOADER_IMAGE_NAME);
}
/**
* {@inheritDoc}
*/
@Override
public void setBootloaderImageFile(File bootloaderImgFile, String version) {
setImageFile(BOOTLOADER_IMAGE_NAME, bootloaderImgFile, version);
}
/**
* {@inheritDoc}
*/
@Override
public void cleanUp() {
for (ImageFile fileRecord : mImageFileMap.values()) {
FileUtil.recursiveDelete(fileRecord.getImageFile());
}
mImageFileMap.clear();
}
/**
* {@inheritDoc}
*/
@Override
public IBuildInfo clone() {
try {
DeviceBuildInfo copy = new DeviceBuildInfo(getBuildId(), getTestTag(),
getBuildTargetName());
copy.addAllBuildAttributes(this);
for (Map.Entry<String, ImageFile> fileEntry : mImageFileMap.entrySet()) {
File origImageFile = fileEntry.getValue().getImageFile();
File hardlinkFile;
if (origImageFile.isDirectory()) {
hardlinkFile = FileUtil.createTempDir(fileEntry.getKey());
FileUtil.recursiveHardlink(origImageFile, hardlinkFile);
} else {
// Only using createTempFile to create a unique dest filename
hardlinkFile = FileUtil.createTempFile(fileEntry.getKey(),
FileUtil.getExtension(origImageFile.getName()));
hardlinkFile.delete();
FileUtil.hardlinkFile(origImageFile, hardlinkFile);
}
copy.mImageFileMap.put(fileEntry.getKey(), new ImageFile(hardlinkFile,
fileEntry.getValue().getVersion()));
}
return copy;
} catch (IOException e) {
throw new RuntimeException(e);
}
}
/**
* Override finalize to determine when a DeviceBuildInfo is being destroyed without having been
* cleaned up. This is temporary as we try to hunt down file leaks.
*/
@Override
protected void finalize() throws Throwable {
super.finalize();
String name = String.format("%s[%s]", LOG_TAG, Thread.currentThread().getName());
Log.d(LOG_TAG, String.format("%s in finalizer", name));
if (!mImageFileMap.isEmpty()) {
Log.e(LOG_TAG, String.format("%s was not cleaned up: %s", name,
mImageFileMap.toString()));
cleanUp();
}
}
}