• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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      */
isFileExist(final String name)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      */
convertRawImageToBufferedImage(RawImage rawImage)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          */
visitFile(File f)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      */
visitAllFilesUnder(File root, FilenameFilter filter, FileVisitor visitor)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      */
visitAllFilesUnder(String path, FilenameFilter filter, FileVisitor visitor)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 
ZipFileVisitor(ZipOutputStream zipOutputStream, ZipFilenameTransformer transformer)151         public ZipFileVisitor(ZipOutputStream zipOutputStream,
152                 ZipFilenameTransformer transformer) {
153             this.zipOutputStream = zipOutputStream;
154             this.transformer = transformer;
155         }
156 
visitFile(File f)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          */
isOk()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          */
getCaughtException()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 {
ZipFileException(IOException ioException)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          */
transform(String filename)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      */
zipUpDirectory(String sourceDir, String outputFilePath, ZipFilenameTransformer transformer)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      */
getFormattedTimeString(long milliSec, String separator, String dateSeparator, String timeSeparator)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      */
toHexString(byte[] arr)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      */
replaceControlChars(String s)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 
dateFromString(String s)314     public static Date dateFromString(String s) throws ParseException {
315         return dateFormat.parse(s);
316     }
317 
dateToString(Date d)318     public static String dateToString(Date d) {
319         return dateFormat.format(d);
320     }
321 }
322