在android-R中,google拓展了原本的UnsupportedAppUsage来限制framework中的某些定义无法被外部应用访问。采用这中方案来强化mainlane模式,强制厂商mainlane自身feature。google也拓展了systemApi注释来保护某些属性无法被sdk外部访问。
@UnsupportedAppUsage
这个注释简单来说就是不支持外部应用使用被此注释声明的变量或方法等
tools\platform-compat\java\android\compat\annotation\UnsupportedAppUsage.java
/**
* Indicates that this non-SDK interface is used by apps. A non-SDK interface is a
* class member (field or method) that is not part of the public SDK. Since the
* member is not part of the SDK, usage by apps is not supported.
*
* <h2>If you are an Android App developer</h2>
*
* This annotation indicates that you may be able to access the member at runtime, but that
* this access is discouraged and not supported by Android. If there is a value
* for {@link #maxTargetSdk()} on the annotation, access will be restricted based
* on the {@code targetSdkVersion} value set in your manifest.
*
* <p>Fields and methods annotated with this are likely to be restricted, changed
* or removed in future Android releases. If you rely on these members for
* functionality that is not otherwise supported by Android, consider filing a
* <a href="http://g.co/dev/appcompat">feature request</a>.
*
* <h2>If you are an Android OS developer</h2>
*
* This annotation acts as a heads up that changing a given method or field
* may affect apps, potentially breaking them when the next Android version is
* released. In some cases, for members that are heavily used, this annotation
* may imply restrictions on changes to the member.
*
* <p>This annotation also results in access to the member being permitted by the
* runtime, with a warning being generated in debug builds. Which apps can access
* the member is determined by the value of {@link #maxTargetSdk()}.
*
* <p>For more details, see go/UnsupportedAppUsage.
*
* {@hide}
*/
@Retention(CLASS)
@Target({CONSTRUCTOR, METHOD, FIELD, TYPE})
@Repeatable(UnsupportedAppUsage.Container.class)
public @interface UnsupportedAppUsage {
@Retention(CLASS)可以看到这个注释是存在于class文件中,也就是说编译器会在编译当前java文件为class文件时保留此注释。
tools/platform-compat/java/android/processor/compat/unsupportedappusage/UnsupportedAppUsageProcessor.java
在UnsupportedAppUsageProcessor.java类中,编译器会在class文件处理阶段对UnsupportedAppUsage注释进行分析处理
@Override
protected void process(TypeElement annotation,
Table<PackageElement, String, List<Element>> annotatedElements) {
SignatureConverter signatureConverter = new SignatureConverter(messager);
for (PackageElement packageElement : annotatedElements.rowKeySet()) {
Map<String, List<Element>> row = annotatedElements.row(packageElement);
for (String enclosingElementName : row.keySet()) {
List<String> content = new ArrayList<>();
for (Element annotatedElement : row.get(enclosingElementName)) {
String signature = signatureConverter.getSignature(
types, annotation, annotatedElement);
if (signature != null) {
String annotationIndex = getAnnotationIndex(signature, annotation,
annotatedElement);
if (annotationIndex != null) {
content.add(annotationIndex);
}
}
}
if (content.isEmpty()) {
continue;
}
try {
FileObject resource = processingEnv.getFiler().createResource(
CLASS_OUTPUT,
packageElement.toString(),
enclosingElementName + GENERATED_INDEX_FILE_EXTENSION);
try (PrintStream outputStream = new PrintStream(resource.openOutputStream())) {
outputStream.println(CSV_HEADER);
content.forEach(outputStream::println);
}
} catch (IOException exception) {
messager.printMessage(ERROR, "Could not write CSV file: " + exception);
}
}
}
}
1.在保存csv后,编译器就知道了当前类中那些属性被UnsupportedAppUsage保护了。
2.在编译其他模块时,在检查当前模块使用的内容时,会检查app是否引用了被注释保护的属性。
3.一旦检查没有通过,就会报编译错误,导致编译失败。