blob: 0731b493e354fb584fc74396a9bddec41050fcb9 [file] [log] [blame]
The Android Open Source Projectf8057102009-03-15 16:47:16 -07001/*
2 * Copyright (C) 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 */
16import java.io.BufferedWriter;
17import java.io.File;
18import java.io.FileNotFoundException;
19import java.io.FileOutputStream;
20import java.io.FileWriter;
21import java.io.IOException;
22import java.util.ArrayList;
23import java.util.Collection;
24import java.util.Iterator;
25
26import javax.xml.parsers.DocumentBuilderFactory;
27import javax.xml.parsers.ParserConfigurationException;
28import javax.xml.transform.Transformer;
29import javax.xml.transform.TransformerException;
30import javax.xml.transform.TransformerFactory;
31import javax.xml.transform.TransformerFactoryConfigurationError;
32import javax.xml.transform.dom.DOMSource;
33import javax.xml.transform.stream.StreamResult;
34
35import org.w3c.dom.Attr;
36import org.w3c.dom.Document;
37import org.w3c.dom.Node;
38import org.w3c.dom.NodeList;
39
Brian Muramatsu7f64e852011-02-17 16:52:16 -080040import vogar.ExpectationStore;
41
The Android Open Source Projectf8057102009-03-15 16:47:16 -070042import com.sun.javadoc.AnnotationDesc;
43import com.sun.javadoc.AnnotationTypeDoc;
44import com.sun.javadoc.AnnotationValue;
45import com.sun.javadoc.ClassDoc;
46import com.sun.javadoc.Doclet;
47import com.sun.javadoc.MethodDoc;
48import com.sun.javadoc.RootDoc;
49import com.sun.javadoc.AnnotationDesc.ElementValuePair;
50
51/**
52 * This is only a very simple and brief JavaDoc parser for the CTS.
53 *
54 * Input: The source files of the test cases. It will be represented
55 * as a list of ClassDoc
56 * Output: Generate file description.xml, which defines the TestPackage
57 * TestSuite and TestCases.
58 *
59 * Note:
60 * 1. Since this class has dependencies on com.sun.javadoc package which
61 * is not implemented on Android. So this class can't be compiled.
62 * 2. The TestSuite can be embedded, which means:
63 * TestPackage := TestSuite*
64 * TestSuite := TestSuite* | TestCase*
65 */
66public class DescriptionGenerator extends Doclet {
67 static final String HOST_CONTROLLER = "dalvik.annotation.HostController";
68 static final String KNOWN_FAILURE = "dalvik.annotation.KnownFailure";
Urs Grobfc77f6e2009-04-17 02:07:14 -070069 static final String BROKEN_TEST = "dalvik.annotation.BrokenTest";
Brian Muramatsu282c6fe2011-01-18 17:14:15 -080070 static final String SIDE_EFFECT = "dalvik.annotation.SideEffect";
Brian Muramatsu168beb02010-10-21 12:39:45 -070071 static final String SUPPRESSED_TEST = "android.test.suitebuilder.annotation.Suppress";
Brian Muramatsu7f64e852011-02-17 16:52:16 -080072 static final String CTS_EXPECTATION_DIR = "cts/tests/expectations";
The Android Open Source Projectf8057102009-03-15 16:47:16 -070073
74 static final String JUNIT_TEST_CASE_CLASS_NAME = "junit.framework.testcase";
75 static final String TAG_PACKAGE = "TestPackage";
76 static final String TAG_SUITE = "TestSuite";
77 static final String TAG_CASE = "TestCase";
78 static final String TAG_TEST = "Test";
79 static final String TAG_DESCRIPTION = "Description";
80
81 static final String ATTRIBUTE_NAME_VERSION = "version";
82 static final String ATTRIBUTE_VALUE_VERSION = "1.0";
83 static final String ATTRIBUTE_NAME_FRAMEWORK = "AndroidFramework";
84 static final String ATTRIBUTE_VALUE_FRAMEWORK = "Android 1.0";
85
86 static final String ATTRIBUTE_NAME = "name";
The Android Open Source Projectf8057102009-03-15 16:47:16 -070087 static final String ATTRIBUTE_HOST_CONTROLLER = "HostController";
The Android Open Source Projectf8057102009-03-15 16:47:16 -070088
89 static final String XML_OUTPUT_PATH = "./description.xml";
90
Phil Dubach0d6ef062009-08-12 18:13:16 -070091 static final String OUTPUT_PATH_OPTION = "-o";
92
The Android Open Source Projectf8057102009-03-15 16:47:16 -070093 /**
94 * Start to parse the classes passed in by javadoc, and generate
95 * the xml file needed by CTS packer.
96 *
97 * @param root The root document passed in by javadoc.
98 * @return Whether the document has been processed.
99 */
100 public static boolean start(RootDoc root) {
101 ClassDoc[] classes = root.classes();
102 if (classes == null) {
103 Log.e("No class found!", null);
104 return true;
105 }
106
Phil Dubach0d6ef062009-08-12 18:13:16 -0700107 String outputPath = XML_OUTPUT_PATH;
108 String[][] options = root.options();
109 for (String[] option : options) {
110 if (option.length == 2 && option[0].equals(OUTPUT_PATH_OPTION)) {
111 outputPath = option[1];
112 }
113 }
114
The Android Open Source Projectf8057102009-03-15 16:47:16 -0700115 XMLGenerator xmlGenerator = null;
116 try {
Phil Dubach0d6ef062009-08-12 18:13:16 -0700117 xmlGenerator = new XMLGenerator(outputPath);
The Android Open Source Projectf8057102009-03-15 16:47:16 -0700118 } catch (ParserConfigurationException e) {
119 Log.e("Cant initialize XML Generator!", e);
120 return true;
121 }
122
Brian Muramatsu7f64e852011-02-17 16:52:16 -0800123 ExpectationStore ctsExpectationStore = null;
124 try {
125 ctsExpectationStore = VogarUtils.provideExpectationStore("./" + CTS_EXPECTATION_DIR);
126 } catch (IOException e) {
127 Log.e("Couldn't load expectation store.", e);
128 return false;
129 }
130
The Android Open Source Projectf8057102009-03-15 16:47:16 -0700131 for (ClassDoc clazz : classes) {
132 if ((!clazz.isAbstract()) && (isValidJUnitTestCase(clazz))) {
Brian Muramatsu7f64e852011-02-17 16:52:16 -0800133 xmlGenerator.addTestClass(new TestClass(clazz, ctsExpectationStore));
The Android Open Source Projectf8057102009-03-15 16:47:16 -0700134 }
135 }
136
137 try {
138 xmlGenerator.dump();
139 } catch (Exception e) {
140 Log.e("Can't dump to XML file!", e);
141 }
142
143 return true;
144 }
145
146 /**
Phil Dubach0d6ef062009-08-12 18:13:16 -0700147 * Return the length of any doclet options we recognize
148 * @param option The option name
149 * @return The number of words this option takes (including the option) or 0 if the option
150 * is not recognized.
151 */
152 public static int optionLength(String option) {
153 if (option.equals(OUTPUT_PATH_OPTION)) {
154 return 2;
155 }
156 return 0;
157 }
158
159 /**
The Android Open Source Projectf8057102009-03-15 16:47:16 -0700160 * Check if the class is valid test case inherited from JUnit TestCase.
161 *
162 * @param clazz The class to be checked.
163 * @return If the class is valid test case inherited from JUnit TestCase, return true;
164 * else, return false.
165 */
166 static boolean isValidJUnitTestCase(ClassDoc clazz) {
167 while((clazz = clazz.superclass()) != null) {
168 if (JUNIT_TEST_CASE_CLASS_NAME.equals(clazz.qualifiedName().toLowerCase())) {
169 return true;
170 }
171 }
172
173 return false;
174 }
175
176 /**
177 * Log utility.
178 */
179 static class Log {
180 private static boolean TRACE = true;
181 private static BufferedWriter mTraceOutput = null;
182
183 /**
184 * Log the specified message.
185 *
186 * @param msg The message to be logged.
187 */
188 static void e(String msg, Exception e) {
189 System.out.println(msg);
190
191 if (e != null) {
192 e.printStackTrace();
193 }
194 }
195
196 /**
197 * Add the message to the trace stream.
198 *
199 * @param msg The message to be added to the trace stream.
200 */
201 public static void t(String msg) {
202 if (TRACE) {
203 try {
204 if ((mTraceOutput != null) && (msg != null)) {
205 mTraceOutput.write(msg + "\n");
206 mTraceOutput.flush();
207 }
208 } catch (IOException e) {
209 e.printStackTrace();
210 }
211 }
212 }
213
214 /**
215 * Initialize the trace stream.
216 *
217 * @param name The class name.
218 */
219 public static void initTrace(String name) {
220 if (TRACE) {
221 try {
222 if (mTraceOutput == null) {
223 String fileName = "cts_debug_dg_" + name + ".txt";
224 mTraceOutput = new BufferedWriter(new FileWriter(fileName));
225 }
226 } catch (IOException e) {
227 e.printStackTrace();
228 }
229 }
230 }
231
232 /**
233 * Close the trace stream.
234 */
235 public static void closeTrace() {
236 if (mTraceOutput != null) {
237 try {
238 mTraceOutput.close();
239 mTraceOutput = null;
240 } catch (IOException e) {
241 e.printStackTrace();
242 }
243 }
244 }
245 }
246
247 static class XMLGenerator {
248 String mOutputPath;
249
250 /**
251 * This document is used to represent the description XML file.
252 * It is construct by the classes passed in, which contains the
253 * information of all the test package, test suite and test cases.
254 */
255 Document mDoc;
256
257 XMLGenerator(String outputPath) throws ParserConfigurationException {
258 mOutputPath = outputPath;
259
260 mDoc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
261
262 Node testPackageElem = mDoc.appendChild(mDoc.createElement(TAG_PACKAGE));
263
The Android Open Source Projectf8057102009-03-15 16:47:16 -0700264 setAttribute(testPackageElem, ATTRIBUTE_NAME_VERSION, ATTRIBUTE_VALUE_VERSION);
265 setAttribute(testPackageElem, ATTRIBUTE_NAME_FRAMEWORK, ATTRIBUTE_VALUE_FRAMEWORK);
266 }
267
268 void addTestClass(TestClass tc) {
269 appendSuiteToElement(mDoc.getDocumentElement(), tc);
270 }
271
272 void dump() throws TransformerFactoryConfigurationError,
273 FileNotFoundException, TransformerException {
274 //rebuildDocument();
275
276 Transformer t = TransformerFactory.newInstance().newTransformer();
277
278 // enable indent in result file
279 t.setOutputProperty("indent", "yes");
280 t.setOutputProperty("{http://xml.apache.org/xslt}indent-amount","4");
281
Jorg Pleumann86192702009-04-21 10:08:53 -0700282 File file = new File(mOutputPath);
283 file.getParentFile().mkdirs();
Scott Su259ced72009-04-30 17:05:49 -0700284
The Android Open Source Projectf8057102009-03-15 16:47:16 -0700285 t.transform(new DOMSource(mDoc),
Jorg Pleumann86192702009-04-21 10:08:53 -0700286 new StreamResult(new FileOutputStream(file)));
The Android Open Source Projectf8057102009-03-15 16:47:16 -0700287 }
288
289 /**
290 * Rebuild the document, merging empty suite nodes.
291 */
292 void rebuildDocument() {
293 // merge empty suite nodes
294 Collection<Node> suiteElems = getUnmutableChildNodes(mDoc.getDocumentElement());
295 Iterator<Node> suiteIterator = suiteElems.iterator();
296 while (suiteIterator.hasNext()) {
297 Node suiteElem = suiteIterator.next();
298
299 mergeEmptySuites(suiteElem);
300 }
301 }
302
303 /**
304 * Merge the test suite which only has one sub-suite. In this case, unify
305 * the name of the two test suites.
306 *
307 * @param suiteElem The suite element of which to be merged.
308 */
309 void mergeEmptySuites(Node suiteElem) {
310 Collection<Node> suiteChildren = getSuiteChildren(suiteElem);
311 if (suiteChildren.size() > 1) {
312 for (Node suiteChild : suiteChildren) {
313 mergeEmptySuites(suiteChild);
314 }
315 } else if (suiteChildren.size() == 1) {
316 // do merge
317 Node child = suiteChildren.iterator().next();
318
319 // update name
320 String newName = getAttribute(suiteElem, ATTRIBUTE_NAME) + "."
321 + getAttribute(child, ATTRIBUTE_NAME);
322 setAttribute(child, ATTRIBUTE_NAME, newName);
323
324 // update parent node
325 Node parentNode = suiteElem.getParentNode();
326 parentNode.removeChild(suiteElem);
327 parentNode.appendChild(child);
328
329 mergeEmptySuites(child);
330 }
331 }
332
333 /**
334 * Get the unmuatable child nodes for specified node.
335 *
336 * @param node The specified node.
337 * @return A collection of copied child node.
338 */
339 private Collection<Node> getUnmutableChildNodes(Node node) {
340 ArrayList<Node> nodes = new ArrayList<Node>();
341 NodeList nodelist = node.getChildNodes();
342
343 for (int i = 0; i < nodelist.getLength(); i++) {
344 nodes.add(nodelist.item(i));
345 }
346
347 return nodes;
348 }
349
350 /**
351 * Append a named test suite to a specified element. Including match with
352 * the existing suite nodes and do the real creation and append.
353 *
354 * @param elem The specified element.
355 * @param testSuite The test suite to be appended.
356 */
357 void appendSuiteToElement(Node elem, TestClass testSuite) {
358 String suiteName = testSuite.mName;
359 Collection<Node> children = getSuiteChildren(elem);
360 int dotIndex = suiteName.indexOf('.');
361 String name = dotIndex == -1 ? suiteName : suiteName.substring(0, dotIndex);
362
363 boolean foundMatch = false;
364 for (Node child : children) {
365 String childName = child.getAttributes().getNamedItem(ATTRIBUTE_NAME)
366 .getNodeValue();
367
368 if (childName.equals(name)) {
369 foundMatch = true;
370 if (dotIndex == -1) {
371 appendTestCases(child, testSuite.mCases);
372 } else {
373 testSuite.mName = suiteName.substring(dotIndex + 1, suiteName.length());
374 appendSuiteToElement(child, testSuite);
375 }
376 }
377
378 }
379
380 if (!foundMatch) {
381 appendSuiteToElementImpl(elem, testSuite);
382 }
383 }
384
385 /**
386 * Get the test suite child nodes of a specified element.
387 *
388 * @param elem The specified element node.
389 * @return The matched child nodes.
390 */
391 Collection<Node> getSuiteChildren(Node elem) {
392 ArrayList<Node> suites = new ArrayList<Node>();
393
394 NodeList children = elem.getChildNodes();
395 for (int i = 0; i < children.getLength(); i++) {
396 Node child = children.item(i);
397
398 if (child.getNodeName().equals(DescriptionGenerator.TAG_SUITE)) {
399 suites.add(child);
400 }
401 }
402
403 return suites;
404 }
405
406 /**
407 * Create test case node according to the given method names, and append them
408 * to the test suite element.
409 *
410 * @param elem The test suite element.
411 * @param cases A collection of test cases included by the test suite class.
412 */
413 void appendTestCases(Node elem, Collection<TestMethod> cases) {
414 if (cases.isEmpty()) {
415 // if no method, remove from parent
416 elem.getParentNode().removeChild(elem);
417 } else {
418 for (TestMethod caze : cases) {
Brian Muramatsu168beb02010-10-21 12:39:45 -0700419 if (caze.mIsBroken || caze.mIsSuppressed || caze.mKnownFailure != null) {
Scott Su259ced72009-04-30 17:05:49 -0700420 continue;
421 }
The Android Open Source Projectf8057102009-03-15 16:47:16 -0700422 Node caseNode = elem.appendChild(mDoc.createElement(TAG_TEST));
423
Phil Dubachdc4e1792009-05-05 14:01:34 -0700424 setAttribute(caseNode, ATTRIBUTE_NAME, caze.mName);
The Android Open Source Projectf8057102009-03-15 16:47:16 -0700425 if ((caze.mController != null) && (caze.mController.length() != 0)) {
426 setAttribute(caseNode, ATTRIBUTE_HOST_CONTROLLER, caze.mController);
427 }
428
The Android Open Source Projectf8057102009-03-15 16:47:16 -0700429 if (caze.mDescription != null && !caze.mDescription.equals("")) {
430 caseNode.appendChild(mDoc.createElement(TAG_DESCRIPTION))
431 .setTextContent(caze.mDescription);
432 }
433 }
434 }
435 }
436
437 /**
438 * Set the attribute of element.
439 *
440 * @param elem The element to be set attribute.
441 * @param name The attribute name.
442 * @param value The attribute value.
443 */
444 protected void setAttribute(Node elem, String name, String value) {
445 Attr attr = mDoc.createAttribute(name);
446 attr.setNodeValue(value);
447
448 elem.getAttributes().setNamedItem(attr);
449 }
450
451 /**
452 * Get the value of a specified attribute of an element.
453 *
454 * @param elem The element node.
455 * @param name The attribute name.
456 * @return The value of the specified attribute.
457 */
458 private String getAttribute(Node elem, String name) {
459 return elem.getAttributes().getNamedItem(name).getNodeValue();
460 }
461
462 /**
463 * Do the append, including creating test suite nodes and test case nodes, and
464 * append them to the element.
465 *
466 * @param elem The specified element node.
467 * @param testSuite The test suite to be append.
468 */
469 void appendSuiteToElementImpl(Node elem, TestClass testSuite) {
470 Node parent = elem;
471 String suiteName = testSuite.mName;
472
473 int dotIndex;
474 while ((dotIndex = suiteName.indexOf('.')) != -1) {
475 String name = suiteName.substring(0, dotIndex);
476
477 Node suiteElem = parent.appendChild(mDoc.createElement(TAG_SUITE));
478 setAttribute(suiteElem, ATTRIBUTE_NAME, name);
479
480 parent = suiteElem;
481 suiteName = suiteName.substring(dotIndex + 1, suiteName.length());
482 }
483
484 Node leafSuiteElem = parent.appendChild(mDoc.createElement(TAG_CASE));
485 setAttribute(leafSuiteElem, ATTRIBUTE_NAME, suiteName);
486
487 appendTestCases(leafSuiteElem, testSuite.mCases);
488 }
489 }
490
491 /**
492 * Represent the test class.
493 */
494 static class TestClass {
495 String mName;
496 Collection<TestMethod> mCases;
497
498 /**
499 * Construct an test suite object.
500 *
501 * @param name Full name of the test suite, such as "com.google.android.Foo"
502 * @param cases The test cases included in this test suite.
503 */
504 TestClass(String name, Collection<TestMethod> cases) {
505 mName = name;
506 mCases = cases;
507 }
508
509 /**
510 * Construct a TestClass object using ClassDoc.
511 *
512 * @param clazz The specified ClassDoc.
513 */
Brian Muramatsu7f64e852011-02-17 16:52:16 -0800514 TestClass(ClassDoc clazz, ExpectationStore expectationStore) {
The Android Open Source Projectf8057102009-03-15 16:47:16 -0700515 mName = clazz.toString();
Brian Muramatsu7f64e852011-02-17 16:52:16 -0800516 mCases = getTestMethods(expectationStore, clazz);
The Android Open Source Projectf8057102009-03-15 16:47:16 -0700517 }
518
519 /**
520 * Get all the TestMethod from a ClassDoc, including inherited methods.
521 *
522 * @param clazz The specified ClassDoc.
523 * @return A collection of TestMethod.
524 */
Brian Muramatsu7f64e852011-02-17 16:52:16 -0800525 Collection<TestMethod> getTestMethods(ExpectationStore expectationStore, ClassDoc clazz) {
The Android Open Source Projectf8057102009-03-15 16:47:16 -0700526 Collection<MethodDoc> methods = getAllMethods(clazz);
527
528 ArrayList<TestMethod> cases = new ArrayList<TestMethod>();
529 Iterator<MethodDoc> iterator = methods.iterator();
530
531 while (iterator.hasNext()) {
532 MethodDoc method = iterator.next();
533
534 String name = method.name();
535
536 AnnotationDesc[] annotations = method.annotations();
537 String controller = "";
538 String knownFailure = null;
Scott Su259ced72009-04-30 17:05:49 -0700539 boolean isBroken = false;
Brian Muramatsu168beb02010-10-21 12:39:45 -0700540 boolean isSuppressed = false;
The Android Open Source Projectf8057102009-03-15 16:47:16 -0700541 for (AnnotationDesc cAnnot : annotations) {
542
543 AnnotationTypeDoc atype = cAnnot.annotationType();
544 if (atype.toString().equals(HOST_CONTROLLER)) {
545 controller = getAnnotationDescription(cAnnot);
546 } else if (atype.toString().equals(KNOWN_FAILURE)) {
547 knownFailure = getAnnotationDescription(cAnnot);
Scott Su259ced72009-04-30 17:05:49 -0700548 } else if (atype.toString().equals(BROKEN_TEST)) {
549 isBroken = true;
Brian Muramatsu168beb02010-10-21 12:39:45 -0700550 } else if (atype.toString().equals(SUPPRESSED_TEST)) {
551 isSuppressed = true;
The Android Open Source Projectf8057102009-03-15 16:47:16 -0700552 }
553 }
554
Brian Muramatsu7f64e852011-02-17 16:52:16 -0800555 if (VogarUtils.isVogarKnownFailure(expectationStore, clazz.toString(), name)) {
556 isBroken = true;
557 }
558
The Android Open Source Projectf8057102009-03-15 16:47:16 -0700559 if (name.startsWith("test")) {
Scott Su259ced72009-04-30 17:05:49 -0700560 cases.add(new TestMethod(name, method.commentText(), controller, knownFailure,
Brian Muramatsu168beb02010-10-21 12:39:45 -0700561 isBroken, isSuppressed));
The Android Open Source Projectf8057102009-03-15 16:47:16 -0700562 }
563 }
564
565 return cases;
566 }
567
568 /**
569 * Get annotation description.
570 *
571 * @param cAnnot The annotation.
572 */
573 String getAnnotationDescription(AnnotationDesc cAnnot) {
574 ElementValuePair[] cpairs = cAnnot.elementValues();
575 ElementValuePair evp = cpairs[0];
576 AnnotationValue av = evp.value();
577 String description = av.toString();
578 // FIXME: need to find out the reason why there are leading and trailing "
579 description = description.substring(1, description.length() -1);
580 return description;
581 }
582
583 /**
584 * Get all MethodDoc of a ClassDoc, including inherited methods.
585 *
586 * @param clazz The specified ClassDoc.
587 * @return A collection of MethodDoc.
588 */
589 Collection<MethodDoc> getAllMethods(ClassDoc clazz) {
590 ArrayList<MethodDoc> methods = new ArrayList<MethodDoc>();
591
592 for (MethodDoc method : clazz.methods()) {
593 methods.add(method);
594 }
595
596 ClassDoc superClass = clazz.superclass();
597 while (superClass != null) {
598 for (MethodDoc method : superClass.methods()) {
599 methods.add(method);
600 }
601
602 superClass = superClass.superclass();
603 }
604
605 return methods;
606 }
607
608 }
609
610 /**
611 * Represent the test method inside the test class.
612 */
613 static class TestMethod {
614 String mName;
615 String mDescription;
616 String mController;
617 String mKnownFailure;
Scott Su259ced72009-04-30 17:05:49 -0700618 boolean mIsBroken;
Brian Muramatsu168beb02010-10-21 12:39:45 -0700619 boolean mIsSuppressed;
The Android Open Source Projectf8057102009-03-15 16:47:16 -0700620
621 /**
622 * Construct an test case object.
623 *
624 * @param name The name of the test case.
625 * @param description The description of the test case.
626 * @param knownFailure The reason of known failure.
627 */
Scott Su259ced72009-04-30 17:05:49 -0700628 TestMethod(String name, String description, String controller, String knownFailure,
Brian Muramatsu168beb02010-10-21 12:39:45 -0700629 boolean isBroken, boolean isSuppressed) {
The Android Open Source Projectf8057102009-03-15 16:47:16 -0700630 mName = name;
631 mDescription = description;
632 mController = controller;
633 mKnownFailure = knownFailure;
Scott Su259ced72009-04-30 17:05:49 -0700634 mIsBroken = isBroken;
Brian Muramatsu168beb02010-10-21 12:39:45 -0700635 mIsSuppressed = isSuppressed;
The Android Open Source Projectf8057102009-03-15 16:47:16 -0700636 }
637 }
638}