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 = new BufferedInputStream(new FileInputStream(f));
    166                 byte[] buffer = new byte[4096];
    167                 int bytesRead = is.read(buffer);
    168                 while (bytesRead > 0) {
    169                     zipOutputStream.write(buffer, 0, bytesRead);
    170                     bytesRead = is.read(buffer);
    171                 }
    172                 zipOutputStream.closeEntry();
    173             } catch (IOException e) {
    174                 ok = false;
    175                 caughtException = e;
    176             }
    177         }
    178 
    179         /**
    180          * Indicates that the visitor ran without errors
    181          * @return true if everything ran OK.
    182          */
    183         boolean isOk() {
    184             return ok;
    185         }
    186 
    187         /**
    188          * If an IOException was thrown while zipping, it gets kept here.
    189          *
    190          * @return the IOException that was caught, or null if none was.
    191          */
    192         IOException getCaughtException() {
    193             return caughtException;
    194         }
    195 
    196     }
    197 
    198     /**
    199      * Indicates some issue with zipping up the file.
    200      */
    201     static class ZipFileException extends Exception {
    202         ZipFileException(IOException ioException) {
    203             super("Caught wrapped exception", ioException);
    204         }
    205     }
    206 
    207     /**
    208      * Interface provided to rename files before they get zipped.
    209      */
    210     public interface ZipFilenameTransformer {
    211         /**
    212          * Transform a local filesystem filename into a zipfile filename.
    213          *
    214          * @param filename the input filename
    215          * @return the filename to be saved to the zipfile as.
    216          */
    217         String transform(String filename);
    218     }
    219 
    220     /**
    221      * Recursively zip up a directory into a zip file.
    222      *
    223      * @param sourceDir the directory to zip up
    224      * @param outputFilePath the zipfile to create.
    225      * @param transformer filepath transformer.  can be null.
    226      * @throws IOException if there were issues writing the zipfile.
    227      */
    228     public static void zipUpDirectory(String sourceDir,
    229             String outputFilePath,
    230             ZipFilenameTransformer transformer)
    231     throws IOException, ZipFileException {
    232         // I <3 abstractions
    233         FileOutputStream fileOut = new FileOutputStream(outputFilePath);
    234         BufferedOutputStream bufOut = new BufferedOutputStream(fileOut);
    235         final ZipOutputStream zipOutputStream = new ZipOutputStream(bufOut);
    236 
    237         ZipFileVisitor zfv = new ZipFileVisitor(zipOutputStream, transformer);
    238         visitAllFilesUnder(sourceDir, null, zfv);
    239         zipOutputStream.close();
    240         if (!zfv.isOk()) {
    241             throw new ZipFileException(zfv.getCaughtException());
    242         }
    243     }
    244 
    245     /**
    246      * Get the formatted time string.
    247      *
    248      * @param milliSec The time in milliseconds.
    249      * @param separator The separator between the date information and time information.
    250      * @param dateSeparator The date separator separating the date information nibbles.
    251      * @param timeSeparator The time separator separating the time information nibbles.
    252      * @return The formated time string.
    253      */
    254     public static String getFormattedTimeString(long milliSec, String separator,
    255             String dateSeparator, String timeSeparator) {
    256         Calendar cal = Calendar.getInstance();
    257         cal.setTimeInMillis(milliSec);
    258         int year  = cal.get(Calendar.YEAR);
    259         int month = cal.get(Calendar.MONTH) + 1;
    260         int date  = cal.get(Calendar.DATE);
    261         int hour  = cal.get(Calendar.HOUR_OF_DAY);
    262         int min   = cal.get(Calendar.MINUTE);
    263         int sec   = cal.get(Calendar.SECOND);
    264 
    265         Formatter fmt = new Formatter();
    266         if ((separator == null) || (separator.length() == 0)) {
    267             separator = "_";
    268         }
    269 
    270         if ((dateSeparator == null) || (dateSeparator.length() == 0)) {
    271             dateSeparator = ".";
    272         }
    273 
    274         if ((timeSeparator == null) || (timeSeparator.length() == 0)) {
    275             timeSeparator = ".";
    276         }
    277 
    278         final String formatStr = "%4d" + dateSeparator + "%02d" + dateSeparator + "%02d"
    279                          + separator + "%02d" + timeSeparator + "%02d" + timeSeparator + "%02d";
    280         fmt.format(formatStr, year, month, date, hour, min, sec);
    281 
    282         return fmt.toString();
    283     }
    284 
    285     /**
    286      * Convert the given byte array into a lowercase hex string.
    287      *
    288      * @param arr The array to convert.
    289      * @return The hex encoded string.
    290      */
    291     public static String toHexString(byte[] arr) {
    292         StringBuffer buf = new StringBuffer(arr.length * 2);
    293         for (byte b : arr) {
    294             buf.append(String.format("%02x", b & 0xFF));
    295         }
    296         return buf.toString();
    297     }
    298 
    299     /**
    300      * Strip control characters from the given string.
    301      */
    302     public static String replaceControlChars(String s) {
    303         // Replace any character < 0x20, except for tab, lf and cr
    304         return s.replaceAll("[\\x00-\\x1f&&[^\t\n\r]]", "?");
    305     }
    306 
    307     public static Date dateFromString(String s) throws ParseException {
    308         return dateFormat.parse(s);
    309     }
    310 
    311     public static String dateToString(Date d) {
    312         return dateFormat.format(d);
    313     }
    314 }
    315