1 /* 2 * Copyright (C) 2011 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 android.signature.cts.api; 18 19 import android.os.Bundle; 20 import android.signature.cts.AnnotationChecker; 21 import android.signature.cts.ApiDocumentParser; 22 import android.signature.cts.JDiffClassDescription; 23 24 import android.signature.cts.LogHelper; 25 import android.util.Log; 26 import androidx.test.InstrumentationRegistry; 27 import com.android.compatibility.common.util.DynamicConfigDeviceSide; 28 import com.android.compatibility.common.util.PropertyUtil; 29 import java.util.List; 30 31 import java.lang.reflect.Constructor; 32 import java.lang.reflect.Field; 33 import java.lang.reflect.Method; 34 import java.util.function.Predicate; 35 import org.junit.Test; 36 37 /** 38 * Checks that parts of the device's API that are annotated (e.g. with android.annotation.SystemApi) 39 * match the API definition. 40 */ 41 public class AnnotationTest extends AbstractApiTest { 42 43 private static final String TAG = AnnotationTest.class.getSimpleName(); 44 45 private String[] mExpectedApiFiles; 46 private String mAnnotationForExactMatch; 47 48 @Override initializeFromArgs(Bundle instrumentationArgs)49 protected void initializeFromArgs(Bundle instrumentationArgs) throws Exception { 50 mExpectedApiFiles = getCommaSeparatedListRequired(instrumentationArgs, "expected-api-files"); 51 mAnnotationForExactMatch = instrumentationArgs.getString("annotation-for-exact-match"); 52 } 53 androidAutoClassesFilter()54 private Predicate<? super JDiffClassDescription> androidAutoClassesFilter() { 55 if (getInstrumentation().getContext().getPackageManager().hasSystemFeature( 56 "android.hardware.type.automotive")) { 57 return clz -> true; 58 } else { 59 return clz -> !clz.getAbsoluteClassName().startsWith("android.car."); 60 } 61 } 62 63 /** 64 * Tests that the parts of the device's API that are annotated (e.g. with 65 * android.annotation.SystemApi) match the API definition. 66 */ 67 @Test testAnnotation()68 public void testAnnotation() { 69 AnnotationChecker.ResultFilter filter = new AnnotationChecker.ResultFilter() { 70 @Override 71 public boolean skip(Class<?> clazz) { 72 return false; 73 } 74 75 @Override 76 public boolean skip(Constructor<?> ctor) { 77 return false; 78 } 79 80 @Override 81 public boolean skip(Method m) { 82 return false; 83 } 84 85 @Override 86 public boolean skip(Field f) { 87 // The R.styleable class is not part of the API because it's annotated with 88 // @doconly. But the class actually exists in the runtime classpath. To avoid 89 // the mismatch, skip the check for fields from the class. 90 return "android.R$styleable".equals(f.getDeclaringClass().getName()); 91 } 92 }; 93 runWithTestResultObserver(resultObserver -> { 94 AnnotationChecker complianceChecker = new AnnotationChecker(resultObserver, 95 mClassProvider, mAnnotationForExactMatch, filter); 96 97 ApiDocumentParser apiDocumentParser = new ApiDocumentParser(TAG); 98 99 parseApiResourcesAsStream(apiDocumentParser, mExpectedApiFiles) 100 .filter(androidAutoClassesFilter()) 101 .forEach(complianceChecker::checkSignatureCompliance); 102 103 // After done parsing all expected API files, perform any deferred checks. 104 complianceChecker.checkDeferred(); 105 }); 106 } 107 } 108