16bf18bae60ae1ff0bf2407e8db115cbbab6f1b84Guang Zhu/*
26bf18bae60ae1ff0bf2407e8db115cbbab6f1b84Guang Zhu * Copyright (C) 2009 The Android Open Source Project
36bf18bae60ae1ff0bf2407e8db115cbbab6f1b84Guang Zhu *
46bf18bae60ae1ff0bf2407e8db115cbbab6f1b84Guang Zhu * Licensed under the Apache License, Version 2.0 (the "License");
56bf18bae60ae1ff0bf2407e8db115cbbab6f1b84Guang Zhu * you may not use this file except in compliance with the License.
66bf18bae60ae1ff0bf2407e8db115cbbab6f1b84Guang Zhu * You may obtain a copy of the License at
76bf18bae60ae1ff0bf2407e8db115cbbab6f1b84Guang Zhu *
86bf18bae60ae1ff0bf2407e8db115cbbab6f1b84Guang Zhu *      http://www.apache.org/licenses/LICENSE-2.0
96bf18bae60ae1ff0bf2407e8db115cbbab6f1b84Guang Zhu *
106bf18bae60ae1ff0bf2407e8db115cbbab6f1b84Guang Zhu * Unless required by applicable law or agreed to in writing, software
116bf18bae60ae1ff0bf2407e8db115cbbab6f1b84Guang Zhu * distributed under the License is distributed on an "AS IS" BASIS,
126bf18bae60ae1ff0bf2407e8db115cbbab6f1b84Guang Zhu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
136bf18bae60ae1ff0bf2407e8db115cbbab6f1b84Guang Zhu * See the License for the specific language governing permissions and
146bf18bae60ae1ff0bf2407e8db115cbbab6f1b84Guang Zhu * limitations under the License.
156bf18bae60ae1ff0bf2407e8db115cbbab6f1b84Guang Zhu */
166bf18bae60ae1ff0bf2407e8db115cbbab6f1b84Guang Zhu
17f92bd42a702af7047ac4bd7c95b4a82973b7a79dGuang Zhupackage com.android.dumprendertree;
18f92bd42a702af7047ac4bd7c95b4a82973b7a79dGuang Zhu
196bf18bae60ae1ff0bf2407e8db115cbbab6f1b84Guang Zhuimport com.android.dumprendertree.forwarder.ForwardService;
206bf18bae60ae1ff0bf2407e8db115cbbab6f1b84Guang Zhu
21f92bd42a702af7047ac4bd7c95b4a82973b7a79dGuang Zhuimport android.util.Log;
22f92bd42a702af7047ac4bd7c95b4a82973b7a79dGuang Zhu
23f92bd42a702af7047ac4bd7c95b4a82973b7a79dGuang Zhuimport java.io.BufferedOutputStream;
24f92bd42a702af7047ac4bd7c95b4a82973b7a79dGuang Zhuimport java.io.BufferedReader;
25f92bd42a702af7047ac4bd7c95b4a82973b7a79dGuang Zhuimport java.io.File;
26f92bd42a702af7047ac4bd7c95b4a82973b7a79dGuang Zhuimport java.io.FileOutputStream;
27f92bd42a702af7047ac4bd7c95b4a82973b7a79dGuang Zhuimport java.io.FileReader;
285dc4f21ab6360b45f464c1451f8d403dd4df3c63Guang Zhuimport java.io.FileWriter;
29f92bd42a702af7047ac4bd7c95b4a82973b7a79dGuang Zhuimport java.io.IOException;
30ea48cd6dd4e64bcb5c840a12fe052f704510e01cGuang Zhuimport java.util.regex.Pattern;
31f92bd42a702af7047ac4bd7c95b4a82973b7a79dGuang Zhu
32f92bd42a702af7047ac4bd7c95b4a82973b7a79dGuang Zhupublic class FsUtils {
33f92bd42a702af7047ac4bd7c95b4a82973b7a79dGuang Zhu
34f92bd42a702af7047ac4bd7c95b4a82973b7a79dGuang Zhu    private static final String LOGTAG = "FsUtils";
356bf18bae60ae1ff0bf2407e8db115cbbab6f1b84Guang Zhu    static final String HTTP_TESTS_PREFIX = "/sdcard/android/layout_tests/http/tests/";
366bf18bae60ae1ff0bf2407e8db115cbbab6f1b84Guang Zhu    static final String HTTPS_TESTS_PREFIX = "/sdcard/android/layout_tests/http/tests/ssl/";
376bf18bae60ae1ff0bf2407e8db115cbbab6f1b84Guang Zhu    static final String HTTP_LOCAL_TESTS_PREFIX = "/sdcard/android/layout_tests/http/tests/local/";
386bf18bae60ae1ff0bf2407e8db115cbbab6f1b84Guang Zhu    static final String HTTP_MEDIA_TESTS_PREFIX = "/sdcard/android/layout_tests/http/tests/media/";
396bf18bae60ae1ff0bf2407e8db115cbbab6f1b84Guang Zhu    static final String HTTP_WML_TESTS_PREFIX = "/sdcard/android/layout_tests/http/tests/wml/";
406bf18bae60ae1ff0bf2407e8db115cbbab6f1b84Guang Zhu
41f92bd42a702af7047ac4bd7c95b4a82973b7a79dGuang Zhu    private FsUtils() {
42f92bd42a702af7047ac4bd7c95b4a82973b7a79dGuang Zhu        //no creation of instances
43f92bd42a702af7047ac4bd7c95b4a82973b7a79dGuang Zhu    }
44f92bd42a702af7047ac4bd7c95b4a82973b7a79dGuang Zhu
45f92bd42a702af7047ac4bd7c95b4a82973b7a79dGuang Zhu    public static void findLayoutTestsRecursively(BufferedOutputStream bos,
46cf0fd7892b7208ebfa35809b63fc8e4d60e4d466Steve Block            String dir, boolean ignoreResultsInDir) throws IOException {
47f92bd42a702af7047ac4bd7c95b4a82973b7a79dGuang Zhu        Log.v(LOGTAG, "Searching tests under " + dir);
48f92bd42a702af7047ac4bd7c95b4a82973b7a79dGuang Zhu
49f92bd42a702af7047ac4bd7c95b4a82973b7a79dGuang Zhu        File d = new File(dir);
50f92bd42a702af7047ac4bd7c95b4a82973b7a79dGuang Zhu        if (!d.isDirectory()) {
51f92bd42a702af7047ac4bd7c95b4a82973b7a79dGuang Zhu            throw new AssertionError("A directory expected, but got " + dir);
52f92bd42a702af7047ac4bd7c95b4a82973b7a79dGuang Zhu        }
53cf0fd7892b7208ebfa35809b63fc8e4d60e4d466Steve Block        ignoreResultsInDir |= FileFilter.ignoreResult(dir);
54f92bd42a702af7047ac4bd7c95b4a82973b7a79dGuang Zhu
55f92bd42a702af7047ac4bd7c95b4a82973b7a79dGuang Zhu        String[] files = d.list();
56f92bd42a702af7047ac4bd7c95b4a82973b7a79dGuang Zhu        for (int i = 0; i < files.length; i++) {
57f92bd42a702af7047ac4bd7c95b4a82973b7a79dGuang Zhu            String s = dir + "/" + files[i];
58cf0fd7892b7208ebfa35809b63fc8e4d60e4d466Steve Block
59cf0fd7892b7208ebfa35809b63fc8e4d60e4d466Steve Block            File f = new File(s);
60cf0fd7892b7208ebfa35809b63fc8e4d60e4d466Steve Block            if (f.isDirectory()) {
61cf0fd7892b7208ebfa35809b63fc8e4d60e4d466Steve Block                // If this is not a test directory, we don't recurse into it.
62cf0fd7892b7208ebfa35809b63fc8e4d60e4d466Steve Block                if (!FileFilter.isNonTestDir(s)) {
63cf0fd7892b7208ebfa35809b63fc8e4d60e4d466Steve Block                    Log.v(LOGTAG, "Recursing on " + s);
64cf0fd7892b7208ebfa35809b63fc8e4d60e4d466Steve Block                    findLayoutTestsRecursively(bos, s, ignoreResultsInDir);
65cf0fd7892b7208ebfa35809b63fc8e4d60e4d466Steve Block                }
665e8f52f5c5ac97cbc514e72c4fc84b6fa46ebc57Steve Block                continue;
675e8f52f5c5ac97cbc514e72c4fc84b6fa46ebc57Steve Block            }
68cf0fd7892b7208ebfa35809b63fc8e4d60e4d466Steve Block
69cf0fd7892b7208ebfa35809b63fc8e4d60e4d466Steve Block            // If this test should be ignored, we skip it completely.
70f92bd42a702af7047ac4bd7c95b4a82973b7a79dGuang Zhu            if (FileFilter.ignoreTest(s)) {
71cf0fd7892b7208ebfa35809b63fc8e4d60e4d466Steve Block                Log.v(LOGTAG, "Ignoring: " + s);
72f92bd42a702af7047ac4bd7c95b4a82973b7a79dGuang Zhu                continue;
73f92bd42a702af7047ac4bd7c95b4a82973b7a79dGuang Zhu            }
74cf0fd7892b7208ebfa35809b63fc8e4d60e4d466Steve Block
75cf0fd7892b7208ebfa35809b63fc8e4d60e4d466Steve Block            if ((s.toLowerCase().endsWith(".html") || s.toLowerCase().endsWith(".xml"))
76cf0fd7892b7208ebfa35809b63fc8e4d60e4d466Steve Block                    && !s.endsWith("TEMPLATE.html")) {
77cf0fd7892b7208ebfa35809b63fc8e4d60e4d466Steve Block                Log.v(LOGTAG, "Recording " + s);
78f92bd42a702af7047ac4bd7c95b4a82973b7a79dGuang Zhu                bos.write(s.getBytes());
79cf0fd7892b7208ebfa35809b63fc8e4d60e4d466Steve Block                // If the result of this test should be ignored, we still run the test.
80cf0fd7892b7208ebfa35809b63fc8e4d60e4d466Steve Block                if (ignoreResultsInDir || FileFilter.ignoreResult(s)) {
81cf0fd7892b7208ebfa35809b63fc8e4d60e4d466Steve Block                    bos.write((" IGNORE_RESULT").getBytes());
82cf0fd7892b7208ebfa35809b63fc8e4d60e4d466Steve Block                }
83f92bd42a702af7047ac4bd7c95b4a82973b7a79dGuang Zhu                bos.write('\n');
84f92bd42a702af7047ac4bd7c95b4a82973b7a79dGuang Zhu            }
85f92bd42a702af7047ac4bd7c95b4a82973b7a79dGuang Zhu        }
86f92bd42a702af7047ac4bd7c95b4a82973b7a79dGuang Zhu    }
87f92bd42a702af7047ac4bd7c95b4a82973b7a79dGuang Zhu
88f92bd42a702af7047ac4bd7c95b4a82973b7a79dGuang Zhu    public static void updateTestStatus(String statusFile, String s) {
89f92bd42a702af7047ac4bd7c95b4a82973b7a79dGuang Zhu        try {
90f92bd42a702af7047ac4bd7c95b4a82973b7a79dGuang Zhu            BufferedOutputStream bos = new BufferedOutputStream(
91f92bd42a702af7047ac4bd7c95b4a82973b7a79dGuang Zhu                    new FileOutputStream(statusFile));
92f92bd42a702af7047ac4bd7c95b4a82973b7a79dGuang Zhu            bos.write(s.getBytes());
93f92bd42a702af7047ac4bd7c95b4a82973b7a79dGuang Zhu            bos.close();
94f92bd42a702af7047ac4bd7c95b4a82973b7a79dGuang Zhu        } catch (Exception e) {
95f92bd42a702af7047ac4bd7c95b4a82973b7a79dGuang Zhu            Log.e(LOGTAG, "Cannot update file " + statusFile);
96f92bd42a702af7047ac4bd7c95b4a82973b7a79dGuang Zhu        }
97f92bd42a702af7047ac4bd7c95b4a82973b7a79dGuang Zhu    }
98f92bd42a702af7047ac4bd7c95b4a82973b7a79dGuang Zhu
99f92bd42a702af7047ac4bd7c95b4a82973b7a79dGuang Zhu    public static String readTestStatus(String statusFile) {
100f92bd42a702af7047ac4bd7c95b4a82973b7a79dGuang Zhu        // read out the test name it stopped last time.
101f92bd42a702af7047ac4bd7c95b4a82973b7a79dGuang Zhu        String status = null;
102f92bd42a702af7047ac4bd7c95b4a82973b7a79dGuang Zhu        File testStatusFile = new File(statusFile);
103f92bd42a702af7047ac4bd7c95b4a82973b7a79dGuang Zhu        if(testStatusFile.exists()) {
104f92bd42a702af7047ac4bd7c95b4a82973b7a79dGuang Zhu            try {
105f92bd42a702af7047ac4bd7c95b4a82973b7a79dGuang Zhu                BufferedReader inReader = new BufferedReader(
106f92bd42a702af7047ac4bd7c95b4a82973b7a79dGuang Zhu                        new FileReader(testStatusFile));
107f92bd42a702af7047ac4bd7c95b4a82973b7a79dGuang Zhu                status = inReader.readLine();
108f92bd42a702af7047ac4bd7c95b4a82973b7a79dGuang Zhu                inReader.close();
109f92bd42a702af7047ac4bd7c95b4a82973b7a79dGuang Zhu            } catch (IOException e) {
110f92bd42a702af7047ac4bd7c95b4a82973b7a79dGuang Zhu                Log.e(LOGTAG, "Error reading test status.", e);
111f92bd42a702af7047ac4bd7c95b4a82973b7a79dGuang Zhu            }
112f92bd42a702af7047ac4bd7c95b4a82973b7a79dGuang Zhu        }
113f92bd42a702af7047ac4bd7c95b4a82973b7a79dGuang Zhu        return status;
114f92bd42a702af7047ac4bd7c95b4a82973b7a79dGuang Zhu    }
115f92bd42a702af7047ac4bd7c95b4a82973b7a79dGuang Zhu
1166bf18bae60ae1ff0bf2407e8db115cbbab6f1b84Guang Zhu    public static String getTestUrl(String path) {
1176bf18bae60ae1ff0bf2407e8db115cbbab6f1b84Guang Zhu        String url = null;
1186bf18bae60ae1ff0bf2407e8db115cbbab6f1b84Guang Zhu        if (!path.startsWith(HTTP_TESTS_PREFIX)) {
1196bf18bae60ae1ff0bf2407e8db115cbbab6f1b84Guang Zhu            url = "file://" + path;
1206bf18bae60ae1ff0bf2407e8db115cbbab6f1b84Guang Zhu        } else {
1216bf18bae60ae1ff0bf2407e8db115cbbab6f1b84Guang Zhu            ForwardService.getForwardService().startForwardService();
1226bf18bae60ae1ff0bf2407e8db115cbbab6f1b84Guang Zhu            if (path.startsWith(HTTPS_TESTS_PREFIX)) {
1236bf18bae60ae1ff0bf2407e8db115cbbab6f1b84Guang Zhu                // still cut the URL after "http/tests/"
1246bf18bae60ae1ff0bf2407e8db115cbbab6f1b84Guang Zhu                url = "https://127.0.0.1:8443/" + path.substring(HTTP_TESTS_PREFIX.length());
1256bf18bae60ae1ff0bf2407e8db115cbbab6f1b84Guang Zhu            } else if (!path.startsWith(HTTP_LOCAL_TESTS_PREFIX)
1266bf18bae60ae1ff0bf2407e8db115cbbab6f1b84Guang Zhu                    && !path.startsWith(HTTP_MEDIA_TESTS_PREFIX)
1276bf18bae60ae1ff0bf2407e8db115cbbab6f1b84Guang Zhu                    && !path.startsWith(HTTP_WML_TESTS_PREFIX)) {
1286bf18bae60ae1ff0bf2407e8db115cbbab6f1b84Guang Zhu                url = "http://127.0.0.1:8000/" + path.substring(HTTP_TESTS_PREFIX.length());
1296bf18bae60ae1ff0bf2407e8db115cbbab6f1b84Guang Zhu            } else {
1306bf18bae60ae1ff0bf2407e8db115cbbab6f1b84Guang Zhu                url = "file://" + path;
1316bf18bae60ae1ff0bf2407e8db115cbbab6f1b84Guang Zhu            }
1326bf18bae60ae1ff0bf2407e8db115cbbab6f1b84Guang Zhu        }
1336bf18bae60ae1ff0bf2407e8db115cbbab6f1b84Guang Zhu        return url;
1346bf18bae60ae1ff0bf2407e8db115cbbab6f1b84Guang Zhu    }
1356bf18bae60ae1ff0bf2407e8db115cbbab6f1b84Guang Zhu
136ea48cd6dd4e64bcb5c840a12fe052f704510e01cGuang Zhu    public static boolean diffIgnoreSpaces(String file1, String file2)  throws IOException {
137ea48cd6dd4e64bcb5c840a12fe052f704510e01cGuang Zhu        BufferedReader br1 = new BufferedReader(new FileReader(file1));
138ea48cd6dd4e64bcb5c840a12fe052f704510e01cGuang Zhu        BufferedReader br2 = new BufferedReader(new FileReader(file2));
139ea48cd6dd4e64bcb5c840a12fe052f704510e01cGuang Zhu        boolean same = true;
140ea48cd6dd4e64bcb5c840a12fe052f704510e01cGuang Zhu        Pattern trailingSpace = Pattern.compile("\\s+$");
141ea48cd6dd4e64bcb5c840a12fe052f704510e01cGuang Zhu
142ea48cd6dd4e64bcb5c840a12fe052f704510e01cGuang Zhu        while(true) {
143ea48cd6dd4e64bcb5c840a12fe052f704510e01cGuang Zhu            String line1 = br1.readLine();
144ea48cd6dd4e64bcb5c840a12fe052f704510e01cGuang Zhu            String line2 = br2.readLine();
145ea48cd6dd4e64bcb5c840a12fe052f704510e01cGuang Zhu
146ea48cd6dd4e64bcb5c840a12fe052f704510e01cGuang Zhu            if (line1 == null && line2 == null)
147ea48cd6dd4e64bcb5c840a12fe052f704510e01cGuang Zhu                break;
148ea48cd6dd4e64bcb5c840a12fe052f704510e01cGuang Zhu            if (line1 != null) {
149ea48cd6dd4e64bcb5c840a12fe052f704510e01cGuang Zhu                line1 = trailingSpace.matcher(line1).replaceAll("");
150ea48cd6dd4e64bcb5c840a12fe052f704510e01cGuang Zhu            } else {
151ea48cd6dd4e64bcb5c840a12fe052f704510e01cGuang Zhu                line1 = "";
152ea48cd6dd4e64bcb5c840a12fe052f704510e01cGuang Zhu            }
153ea48cd6dd4e64bcb5c840a12fe052f704510e01cGuang Zhu            if (line2 != null) {
154ea48cd6dd4e64bcb5c840a12fe052f704510e01cGuang Zhu                line2 = trailingSpace.matcher(line2).replaceAll("");
155ea48cd6dd4e64bcb5c840a12fe052f704510e01cGuang Zhu            } else {
156ea48cd6dd4e64bcb5c840a12fe052f704510e01cGuang Zhu                line2 = "";
157ea48cd6dd4e64bcb5c840a12fe052f704510e01cGuang Zhu            }
158ea48cd6dd4e64bcb5c840a12fe052f704510e01cGuang Zhu            if(!line1.equals(line2)) {
159ea48cd6dd4e64bcb5c840a12fe052f704510e01cGuang Zhu                same = false;
160ea48cd6dd4e64bcb5c840a12fe052f704510e01cGuang Zhu                break;
161ea48cd6dd4e64bcb5c840a12fe052f704510e01cGuang Zhu            }
162ea48cd6dd4e64bcb5c840a12fe052f704510e01cGuang Zhu        }
163ea48cd6dd4e64bcb5c840a12fe052f704510e01cGuang Zhu
164ea48cd6dd4e64bcb5c840a12fe052f704510e01cGuang Zhu        br1.close();
165ea48cd6dd4e64bcb5c840a12fe052f704510e01cGuang Zhu        br2.close();
166ea48cd6dd4e64bcb5c840a12fe052f704510e01cGuang Zhu
167ea48cd6dd4e64bcb5c840a12fe052f704510e01cGuang Zhu        return same;
168ea48cd6dd4e64bcb5c840a12fe052f704510e01cGuang Zhu    }
169ea48cd6dd4e64bcb5c840a12fe052f704510e01cGuang Zhu
1705dc4f21ab6360b45f464c1451f8d403dd4df3c63Guang Zhu    public static boolean isTestPageUrl(String url) {
1715dc4f21ab6360b45f464c1451f8d403dd4df3c63Guang Zhu        int qmPostion = url.indexOf('?');
1725dc4f21ab6360b45f464c1451f8d403dd4df3c63Guang Zhu        int slashPostion = url.lastIndexOf('/');
1735dc4f21ab6360b45f464c1451f8d403dd4df3c63Guang Zhu        if (slashPostion < qmPostion) {
1745dc4f21ab6360b45f464c1451f8d403dd4df3c63Guang Zhu            String fileName = url.substring(slashPostion + 1, qmPostion);
1755dc4f21ab6360b45f464c1451f8d403dd4df3c63Guang Zhu            if ("index.html".equals(fileName)) {
1765dc4f21ab6360b45f464c1451f8d403dd4df3c63Guang Zhu                return true;
1775dc4f21ab6360b45f464c1451f8d403dd4df3c63Guang Zhu            }
1785dc4f21ab6360b45f464c1451f8d403dd4df3c63Guang Zhu        }
1795dc4f21ab6360b45f464c1451f8d403dd4df3c63Guang Zhu        return false;
1805dc4f21ab6360b45f464c1451f8d403dd4df3c63Guang Zhu    }
1815dc4f21ab6360b45f464c1451f8d403dd4df3c63Guang Zhu
1825dc4f21ab6360b45f464c1451f8d403dd4df3c63Guang Zhu    public static String getLastSegmentInPath(String path) {
1835dc4f21ab6360b45f464c1451f8d403dd4df3c63Guang Zhu        int endPos = path.lastIndexOf('/');
1845dc4f21ab6360b45f464c1451f8d403dd4df3c63Guang Zhu        path = path.substring(0, endPos);
1855dc4f21ab6360b45f464c1451f8d403dd4df3c63Guang Zhu        endPos = path.lastIndexOf('/');
1865dc4f21ab6360b45f464c1451f8d403dd4df3c63Guang Zhu        return path.substring(endPos + 1);
1875dc4f21ab6360b45f464c1451f8d403dd4df3c63Guang Zhu    }
1885dc4f21ab6360b45f464c1451f8d403dd4df3c63Guang Zhu
1895dc4f21ab6360b45f464c1451f8d403dd4df3c63Guang Zhu    public static void writeDrawTime(String fileName, String url, long[] times) {
1905dc4f21ab6360b45f464c1451f8d403dd4df3c63Guang Zhu        StringBuffer lineBuffer = new StringBuffer();
1915dc4f21ab6360b45f464c1451f8d403dd4df3c63Guang Zhu        // grab the last segment of path in url
1925dc4f21ab6360b45f464c1451f8d403dd4df3c63Guang Zhu        lineBuffer.append(getLastSegmentInPath(url));
1935dc4f21ab6360b45f464c1451f8d403dd4df3c63Guang Zhu        for (long time : times) {
1945dc4f21ab6360b45f464c1451f8d403dd4df3c63Guang Zhu            lineBuffer.append('\t');
1955dc4f21ab6360b45f464c1451f8d403dd4df3c63Guang Zhu            lineBuffer.append(time);
1965dc4f21ab6360b45f464c1451f8d403dd4df3c63Guang Zhu        }
1975dc4f21ab6360b45f464c1451f8d403dd4df3c63Guang Zhu        lineBuffer.append('\n');
1985dc4f21ab6360b45f464c1451f8d403dd4df3c63Guang Zhu        String line = lineBuffer.toString();
1995dc4f21ab6360b45f464c1451f8d403dd4df3c63Guang Zhu        Log.v(LOGTAG, "logging draw times: " + line);
2005dc4f21ab6360b45f464c1451f8d403dd4df3c63Guang Zhu        try {
2015dc4f21ab6360b45f464c1451f8d403dd4df3c63Guang Zhu            FileWriter fw = new FileWriter(fileName, true);
2025dc4f21ab6360b45f464c1451f8d403dd4df3c63Guang Zhu            fw.write(line);
2035dc4f21ab6360b45f464c1451f8d403dd4df3c63Guang Zhu            fw.close();
2045dc4f21ab6360b45f464c1451f8d403dd4df3c63Guang Zhu        } catch (IOException ioe) {
2055dc4f21ab6360b45f464c1451f8d403dd4df3c63Guang Zhu            Log.e(LOGTAG, "Failed to log draw times", ioe);
2065dc4f21ab6360b45f464c1451f8d403dd4df3c63Guang Zhu        }
2075dc4f21ab6360b45f464c1451f8d403dd4df3c63Guang Zhu    }
2085dc4f21ab6360b45f464c1451f8d403dd4df3c63Guang Zhu
209f92bd42a702af7047ac4bd7c95b4a82973b7a79dGuang Zhu}
210