Home | History | Annotate | Download | only in cts
      1 /*
      2  * Copyright (C) 2008 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.cts;
     18 
     19 import com.android.ddmlib.RawImage;
     20 
     21 import java.awt.image.BufferedImage;
     22 import java.awt.image.DataBuffer;
     23 import java.awt.image.DataBufferUShort;
     24 import java.awt.image.Raster;
     25 import java.awt.image.SampleModel;
     26 import java.awt.image.SinglePixelPackedSampleModel;
     27 import java.io.BufferedInputStream;
     28 import java.io.BufferedOutputStream;
     29 import java.io.File;
     30 import java.io.FileInputStream;
     31 import java.io.FileOutputStream;
     32 import java.io.FilenameFilter;
     33 import java.io.IOException;
     34 import java.io.InputStream;
     35 import java.text.ParseException;
     36 import java.text.SimpleDateFormat;
     37 import java.util.Calendar;
     38 import java.util.Date;
     39 import java.util.Formatter;
     40 import java.util.Locale;
     41 import java.util.zip.ZipEntry;
     42 import java.util.zip.ZipOutputStream;
     43 
     44 /**
     45  * Utilities for CTS host.
     46  *
     47  */
     48 public class HostUtils {
     49 
     50     private static SimpleDateFormat dateFormat = new SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy",
     51             Locale.ENGLISH);
     52 
     53     /**
     54      * Check if the given file exists
     55      *
     56      * @param name the file name to be checked
     57      * @return if the file exists, return true;
     58      *         else, return false
     59      */
     60     public static boolean isFileExist(final String name) {
     61         return new File(name).exists();
     62     }
     63 
     64     /**
     65      * Convert a 16bpp RawImage into a BufferedImage.
     66      *
     67      * @param rawImage the image to convert.
     68      * @return the BufferedImage.
     69      */
     70     public static BufferedImage convertRawImageToBufferedImage(RawImage rawImage) {
     71         assert rawImage.bpp == 16;
     72 
     73         BufferedImage im = new BufferedImage(rawImage.width,
     74                 rawImage.height, BufferedImage.TYPE_USHORT_565_RGB);
     75         SampleModel sampleModel = new SinglePixelPackedSampleModel(DataBuffer.TYPE_USHORT,
     76                 rawImage.width,
     77                 rawImage.height,
     78                 // RGB565
     79                 new int[] { 0xf800, 0x07e0, 0x001f });
     80 
     81         // It would be more efficient to just subclass DataBuffer and provide a
     82         // TYPE_USHORT interface to the byte array.  But Raster.createRaster at
     83         // some point uses instanceof(DataBufferUShort) to verify that the DataBuffer
     84         // is of the right type (instead of just checking DataBuffer.getDataType).
     85         // And since DataBufferUShort is final, it can't be subclassed to get around
     86         // the check either.  So copy the data into a short[] instead to work around the problem.
     87         short shortData[] = new short[rawImage.size / 2];
     88         for (int x = 0; x < shortData.length; x++) {
     89             int rawImageOffset = x * 2;
     90             int a = 0xff & rawImage.data[rawImageOffset];
     91             int b = 0xff & rawImage.data[rawImageOffset + 1];
     92             shortData[x] = (short)((b << 8) | a);
     93         }
     94         DataBuffer db = new DataBufferUShort(shortData, shortData.length);
     95         Raster raster = Raster.createRaster(sampleModel,
     96                 db, null);
     97         im.setData(raster);
     98         return im;
     99     }
    100 
    101     /**
    102      * Interface used with visitAllFilesUnder
    103      */
    104     public interface FileVisitor {
    105         /**
    106          * Gets called on every file visited.
    107          * @param f the File for the file being visited.
    108          */
    109         void visitFile(File f);
    110     }
    111 
    112     /**
    113      * Recursively visit all files under a given path.
    114      *
    115      * @param root the path to start at.
    116      * @param filter the file filter to match.  null means to visit all files.
    117      * @param visitor the visitor to visit with.
    118      */
    119     public static void visitAllFilesUnder(File root, FilenameFilter filter, FileVisitor visitor) {
    120         File[] files = root.listFiles(filter);
    121         // A null file may indicate not having enough permissions to view that directory
    122         if (files != null) {
    123             for (File f : files) {
    124                 visitor.visitFile(f);
    125 
    126                 if (f.isDirectory()) {
    127                     visitAllFilesUnder(f, filter, visitor);
    128                 }
    129             }
    130         }
    131     }
    132 
    133     /**
    134      * Recursively visit all files under a given path.
    135      *
    136      * @param path the path to start at.
    137      * @param filter the file filter to match.  null means to visit all files.
    138      * @param visitor the visitor to visit with.
    139      */
    140     public static void visitAllFilesUnder(String path, FilenameFilter filter, FileVisitor visitor) {
    141         visitAllFilesUnder(new File(path), filter, visitor);
    142     }
    143 
    144     // Private class to help zipUpDirectory
    145     private static class ZipFileVisitor implements FileVisitor {
    146         private final ZipOutputStream zipOutputStream;
    147         private boolean ok = true;
    148         private IOException caughtException;
    149         private final ZipFilenameTransformer transformer;
    150 
    151         public ZipFileVisitor(ZipOutputStream zipOutputStream,
    152                 ZipFilenameTransformer transformer) {
    153             this.zipOutputStream = zipOutputStream;
    154             this.transformer = transformer;
    155         }
    156 
    157         public void visitFile(File f) {
    158             String path = f.getPath();
    159             if (transformer != null) {
    160                 path = transformer.transform(path);
    161             }
    162             ZipEntry ze = new ZipEntry(path);
    163             try {
    164                 zipOutputStream.putNextEntry(ze);
    165                 InputStream is = null;
    166                 try {
    167                     is = new BufferedInputStream(new FileInputStream(f));
    168                     byte[] buffer = new byte[4096];
    169                     int bytesRead = is.read(buffer);
    170                     while (bytesRead > 0) {
    171                         zipOutputStream.write(buffer, 0, bytesRead);
    172                         bytesRead = is.read(buffer);
    173                     }
    174                     zipOutputStream.closeEntry();
    175                 } finally {
    176                     if (is != null) {
    177                         is.close();
    178                     }
    179                 }
    180             } catch (IOException e) {
    181                 ok = false;
    182                 caughtException = e;
    183             }
    184         }
    185 
    186         /**
    187          * Indicates that the visitor ran without errors
    188          * @return true if everything ran OK.
    189          */
    190         boolean isOk() {
    191             return ok;
    192         }
    193 
    194         /**
    195          * If an IOException was thrown while zipping, it gets kept here.
    196          *
    197          * @return the IOException that was caught, or null if none was.
    198          */
    199         IOException getCaughtException() {
    200             return caughtException;
    201         }
    202 
    203     }
    204 
    205     /**
    206      * Indicates some issue with zipping up the file.
    207      */
    208     static class ZipFileException extends Exception {
    209         ZipFileException(IOException ioException) {
    210             super("Caught wrapped exception", ioException);
    211         }
    212     }
    213 
    214     /**
    215      * Interface provided to rename files before they get zipped.
    216      */
    217     public interface ZipFilenameTransformer {
    218         /**
    219          * Transform a local filesystem filename into a zipfile filename.
    220          *
    221          * @param filename the input filename
    222          * @return the filename to be saved to the zipfile as.
    223          */
    224         String transform(String filename);
    225     }
    226 
    227     /**
    228      * Recursively zip up a directory into a zip file.
    229      *
    230      * @param sourceDir the directory to zip up
    231      * @param outputFilePath the zipfile to create.
    232      * @param transformer filepath transformer.  can be null.
    233      * @throws IOException if there were issues writing the zipfile.
    234      */
    235     public static void zipUpDirectory(String sourceDir,
    236             String outputFilePath,
    237             ZipFilenameTransformer transformer)
    238     throws IOException, ZipFileException {
    239         // I <3 abstractions
    240         FileOutputStream fileOut = new FileOutputStream(outputFilePath);
    241         BufferedOutputStream bufOut = new BufferedOutputStream(fileOut);
    242         final ZipOutputStream zipOutputStream = new ZipOutputStream(bufOut);
    243 
    244         ZipFileVisitor zfv = new ZipFileVisitor(zipOutputStream, transformer);
    245         visitAllFilesUnder(sourceDir, null, zfv);
    246         zipOutputStream.close();
    247         if (!zfv.isOk()) {
    248             throw new ZipFileException(zfv.getCaughtException());
    249         }
    250     }
    251 
    252     /**
    253      * Get the formatted time string.
    254      *
    255      * @param milliSec The time in milliseconds.
    256      * @param separator The separator between the date information and time information.
    257      * @param dateSeparator The date separator separating the date information nibbles.
    258      * @param timeSeparator The time separator separating the time information nibbles.
    259      * @return The formated time string.
    260      */
    261     public static String getFormattedTimeString(long milliSec, String separator,
    262             String dateSeparator, String timeSeparator) {
    263         Calendar cal = Calendar.getInstance();
    264         cal.setTimeInMillis(milliSec);
    265         int year  = cal.get(Calendar.YEAR);
    266         int month = cal.get(Calendar.MONTH) + 1;
    267         int date  = cal.get(Calendar.DATE);
    268         int hour  = cal.get(Calendar.HOUR_OF_DAY);
    269         int min   = cal.get(Calendar.MINUTE);
    270         int sec   = cal.get(Calendar.SECOND);
    271 
    272         Formatter fmt = new Formatter();
    273         if ((separator == null) || (separator.length() == 0)) {
    274             separator = "_";
    275         }
    276 
    277         if ((dateSeparator == null) || (dateSeparator.length() == 0)) {
    278             dateSeparator = ".";
    279         }
    280 
    281         if ((timeSeparator == null) || (timeSeparator.length() == 0)) {
    282             timeSeparator = ".";
    283         }
    284 
    285         final String formatStr = "%4d" + dateSeparator + "%02d" + dateSeparator + "%02d"
    286                          + separator + "%02d" + timeSeparator + "%02d" + timeSeparator + "%02d";
    287         fmt.format(formatStr, year, month, date, hour, min, sec);
    288 
    289         return fmt.toString();
    290     }
    291 
    292     /**
    293      * Convert the given byte array into a lowercase hex string.
    294      *
    295      * @param arr The array to convert.
    296      * @return The hex encoded string.
    297      */
    298     public static String toHexString(byte[] arr) {
    299         StringBuffer buf = new StringBuffer(arr.length * 2);
    300         for (byte b : arr) {
    301             buf.append(String.format("%02x", b & 0xFF));
    302         }
    303         return buf.toString();
    304     }
    305 
    306     /**
    307      * Strip control characters from the given string.
    308      */
    309     public static String replaceControlChars(String s) {
    310         // Replace any character < 0x20, except for tab, lf and cr
    311         return s.replaceAll("[\\x00-\\x1f&&[^\t\n\r]]", "?");
    312     }
    313 
    314     public static Date dateFromString(String s) throws ParseException {
    315         return dateFormat.parse(s);
    316     }
    317 
    318     public static String dateToString(Date d) {
    319         return dateFormat.format(d);
    320     }
    321 }
    322