android系统源码编译报错问题分析处理--持续更新
一、build/make/core/base_rules.mk:232: error: packages/services/Car/service: LOCAL_BUILT_MODULE and LOCAL_INSTALLED_MODULE must not be defined by component makefiles
出现此错误时,需要检查Android.mk中include $(CLEAR_VARS)及include $(BUILD_XXX...)是否一一对应了,如果有类似下边的写法,就需要修正
- 错误:
- ......
- include $(CLEAR_VARS)
- ......
- include $(BUILD_MULTI_PREBUILT)
- ......
- include $(BUILD_STATIC_JAVA_LIBRARY)
- ......
- include $(BUILD_PACKAGE)
- include $(CLEAR_VARS)
- 正确:
- include $(CLEAR_VARS)
- ......
- include $(BUILD_MULTI_PREBUILT)
- include $(CLEAR_VARS)
- ......
- include $(BUILD_STATIC_JAVA_LIBRARY)
- include $(CLEAR_VARS)
- ......
- include $(BUILD_PACKAGE)
二、错误: 程序包androidx.annotation不存在,需要在 Android.mk 中添加如下,根据自己的依赖进行添加
- LOCAL_STATIC_ANDROID_LIBRARIES := \
- androidx.recyclerview_recyclerview \
- androidx.preference_preference \
- androidx.appcompat_appcompat \
- androidx.annotation_annotation \
- androidx.legacy_legacy-preference-v14 \
- androidx.leanback_leanback-preference \
- androidx.leanback_leanback \
三、javadoc: 错误 - 在 doclet 类com.google.doclava.Doclava中, 方法start已抛出异常错误java.lang.reflect.InvocationTargetException
java.lang.IllegalArgumentException: Unable to find IBtMusicCmd.java. This is usually because doclava has been asked to generate stubs for a file that isn't present in the list of input source files but exists in the input classpath.
IBtMusicCmd是我的aidl文件,代码都编译通过了,没有出现依赖问题,但是最后报出这个错,查了两天才发现这个问题应该是javadoc的版本太低了,我找到了这个系统文件进行了暴力修改后编译正常,但是是否存在隐患还不确定
- 解决办法:
- 直接找到external\doclava\src\com\google\doclava\Stubs.java,然后在53行添加if(true) return;如下!目的就是不执行此文件的操作
- public class Stubs {
- public static void writeStubsAndApi(String stubsDir, String apiFile, String dexApiFile,
- String keepListFile, String removedApiFile, String removedDexApiFile, String exactApiFile,
- String privateApiFile, String privateDexApiFile, HashSet<String> stubPackages,
- HashSet<String> stubImportPackages, boolean stubSourceOnly) {
- if(true) return;
如果为了安全一点,也可以按照下边的方式,只判断是自己的这个模块就跳过就好了,源代码里三个地方添加以下代码,“android.car.xxxx.bt”需要替换为自己冲突的模块包名
- if(cl.containingPackage().name().contains("android.car.xxxx.bt")){
- System.out.println("=======android.car.xxxx.bt=============continue");
- continue;
- }


- 1 /*
- 2 * Copyright (C) 2010 Google Inc.
- 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.google.doclava;
- 18
- 19 import java.io.BufferedOutputStream;
- 20 import java.io.BufferedReader;
- 21 import java.io.ByteArrayOutputStream;
- 22 import java.io.File;
- 23 import java.io.FileInputStream;
- 24 import java.io.FileNotFoundException;
- 25 import java.io.FileOutputStream;
- 26 import java.io.IOException;
- 27 import java.io.InputStream;
- 28 import java.io.InputStreamReader;
- 29 import java.io.PrintStream;
- 30 import java.nio.charset.StandardCharsets;
- 31 import java.nio.file.Files;
- 32 import java.nio.file.Paths;
- 33 import java.util.ArrayList;
- 34 import java.util.Arrays;
- 35 import java.util.Collection;
- 36 import java.util.Collections;
- 37 import java.util.HashMap;
- 38 import java.util.HashSet;
- 39 import java.util.Iterator;
- 40 import java.util.List;
- 41 import java.util.Map;
- 42 import java.util.Scanner;
- 43 import java.util.Set;
- 44 import java.util.function.Predicate;
- 45 import java.util.regex.Pattern;
- 46 import java.util.stream.Collectors;
- 47
- 48 public class Stubs {
- 49 public static void writeStubsAndApi(String stubsDir, String apiFile, String dexApiFile,
- 50 String keepListFile, String removedApiFile, String removedDexApiFile, String exactApiFile,
- 51 String privateApiFile, String privateDexApiFile, HashSet<String> stubPackages,
- 52 HashSet<String> stubImportPackages, boolean stubSourceOnly) {
- 53 //if(true) return;
- 54 // figure out which classes we need
- 55 final HashSet<ClassInfo> notStrippable = new HashSet<ClassInfo>();
- 56 Collection<ClassInfo> all = Converter.allClasses();
- 57 Map<PackageInfo, List<ClassInfo>> allClassesByPackage = null;
- 58 PrintStream apiWriter = null;
- 59 PrintStream dexApiWriter = null;
- 60 PrintStream keepListWriter = null;
- 61 PrintStream removedApiWriter = null;
- 62 PrintStream removedDexApiWriter = null;
- 63 PrintStream exactApiWriter = null;
- 64 PrintStream privateApiWriter = null;
- 65 PrintStream privateDexApiWriter = null;
- 66
- 67 if (apiFile != null) {
- 68 try {
- 69 File xml = new File(apiFile);
- 70 xml.getParentFile().mkdirs();
- 71 apiWriter = new PrintStream(new BufferedOutputStream(new FileOutputStream(xml)));
- 72 } catch (FileNotFoundException e) {
- 73 Errors.error(Errors.IO_ERROR, new SourcePositionInfo(apiFile, 0, 0),
- 74 "Cannot open file for write.");
- 75 }
- 76 }
- 77 if (dexApiFile != null) {
- 78 try {
- 79 File dexApi = new File(dexApiFile);
- 80 dexApi.getParentFile().mkdirs();
- 81 dexApiWriter = new PrintStream(new BufferedOutputStream(new FileOutputStream(dexApi)));
- 82 } catch (FileNotFoundException e) {
- 83 Errors.error(Errors.IO_ERROR, new SourcePositionInfo(dexApiFile, 0, 0),
- 84 "Cannot open file for write.");
- 85 }
- 86 }
- 87 if (keepListFile != null) {
- 88 try {
- 89 File keepList = new File(keepListFile);
- 90 keepList.getParentFile().mkdirs();
- 91 keepListWriter = new PrintStream(new BufferedOutputStream(new FileOutputStream(keepList)));
- 92 } catch (FileNotFoundException e) {
- 93 Errors.error(Errors.IO_ERROR, new SourcePositionInfo(keepListFile, 0, 0),
- 94 "Cannot open file for write.");
- 95 }
- 96 }
- 97 if (removedApiFile != null) {
- 98 try {
- 99 File removedApi = new File(removedApiFile);
- 100 removedApi.getParentFile().mkdirs();
- 101 removedApiWriter = new PrintStream(
- 102 new BufferedOutputStream(new FileOutputStream(removedApi)));
- 103 } catch (FileNotFoundException e) {
- 104 Errors.error(Errors.IO_ERROR, new SourcePositionInfo(removedApiFile, 0, 0),
- 105 "Cannot open file for write");
- 106 }
- 107 }
- 108 if (removedDexApiFile != null) {
- 109 try {
- 110 File removedDexApi = new File(removedDexApiFile);
- 111 removedDexApi.getParentFile().mkdirs();
- 112 removedDexApiWriter = new PrintStream(
- 113 new BufferedOutputStream(new FileOutputStream(removedDexApi)));
- 114 } catch (FileNotFoundException e) {
- 115 Errors.error(Errors.IO_ERROR, new SourcePositionInfo(removedDexApiFile, 0, 0),
- 116 "Cannot open file for write");
- 117 }
- 118 }
- 119 if (exactApiFile != null) {
- 120 try {
- 121 File exactApi = new File(exactApiFile);
- 122 exactApi.getParentFile().mkdirs();
- 123 exactApiWriter = new PrintStream(
- 124 new BufferedOutputStream(new FileOutputStream(exactApi)));
- 125 } catch (FileNotFoundException e) {
- 126 Errors.error(Errors.IO_ERROR, new SourcePositionInfo(exactApiFile, 0, 0),
- 127 "Cannot open file for write");
- 128 }
- 129 }
- 130 if (privateApiFile != null) {
- 131 try {
- 132 File privateApi = new File(privateApiFile);
- 133 privateApi.getParentFile().mkdirs();
- 134 privateApiWriter = new PrintStream(
- 135 new BufferedOutputStream(new FileOutputStream(privateApi)));
- 136 } catch (FileNotFoundException e) {
- 137 Errors.error(Errors.IO_ERROR, new SourcePositionInfo(privateApiFile, 0, 0),
- 138 "Cannot open file for write");
- 139 }
- 140 }
- 141 if (privateDexApiFile != null) {
- 142 try {
- 143 File privateDexApi = new File(privateDexApiFile);
- 144 privateDexApi.getParentFile().mkdirs();
- 145 privateDexApiWriter = new PrintStream(
- 146 new BufferedOutputStream(new FileOutputStream(privateDexApi)));
- 147 } catch (FileNotFoundException e) {
- 148 Errors.error(Errors.IO_ERROR, new SourcePositionInfo(privateDexApiFile, 0, 0),
- 149 "Cannot open file for write");
- 150 }
- 151 }
- 152 // If a class is public or protected, not hidden, not imported and marked as included,
- 153 // then we can't strip it
- 154 for (ClassInfo cl : all) {
- 155 if(cl.containingPackage().name().contains("android.car.xxxx.bt")){
- 156 System.out.println("=======android.car.xxxx.bt=============continue");
- 157 continue;
- 158 }
- 159 if (cl.checkLevel() && cl.isIncluded()) {
- 160 cantStripThis(cl, notStrippable, "0:0", stubImportPackages);
- 161 }
- 162 }
- 163
- 164 // complain about anything that looks includeable but is not supposed to
- 165 // be written, e.g. hidden things
- 166 for (ClassInfo cl : notStrippable) {
- 167 if(cl.containingPackage().name().contains("android.car.xxxx.bt")){
- 168 System.out.println("=======android.car.xxxx.bt=============continue");
- 169 continue;
- 170 }
- 171 if (!cl.isHiddenOrRemoved()) {
- 172 for (MethodInfo m : cl.selfMethods()) {
- 173 if (m.isHiddenOrRemoved()) {
- 174 Errors.error(Errors.UNAVAILABLE_SYMBOL, m.position(), "Reference to unavailable method "
- 175 + m.name());
- 176 } else if (m.isDeprecated()) {
- 177 // don't bother reporting deprecated methods
- 178 // unless they are public
- 179 Errors.error(Errors.DEPRECATED, m.position(), "Method " + cl.qualifiedName() + "."
- 180 + m.name() + " is deprecated");
- 181 }
- 182
- 183 ClassInfo hiddenClass = findHiddenClasses(m.returnType(), stubImportPackages);
- 184 if (null != hiddenClass) {
- 185 if (hiddenClass.qualifiedName() == m.returnType().asClassInfo().qualifiedName()) {
- 186 // Return type is hidden
- 187 Errors.error(Errors.UNAVAILABLE_SYMBOL, m.position(), "Method " + cl.qualifiedName()
- 188 + "." + m.name() + " returns unavailable type " + hiddenClass.name());
- 189 } else {
- 190 // Return type contains a generic parameter
- 191 Errors.error(Errors.HIDDEN_TYPE_PARAMETER, m.position(), "Method " + cl.qualifiedName()
- 192 + "." + m.name() + " returns unavailable type " + hiddenClass.name()
- 193 + " as a type parameter");
- 194 }
- 195 }
- 196
- 197 for (ParameterInfo p : m.parameters()) {
- 198 TypeInfo t = p.type();
- 199 if (!t.isPrimitive()) {
- 200 hiddenClass = findHiddenClasses(t, stubImportPackages);
- 201 if (null != hiddenClass) {
- 202 if (hiddenClass.qualifiedName() == t.asClassInfo().qualifiedName()) {
- 203 // Parameter type is hidden
- 204 Errors.error(Errors.UNAVAILABLE_SYMBOL, m.position(),
- 205 "Parameter of unavailable type " + t.fullName() + " in " + cl.qualifiedName()
- 206 + "." + m.name() + "()");
- 207 } else {
- 208 // Parameter type contains a generic parameter
- 209 Errors.error(Errors.HIDDEN_TYPE_PARAMETER, m.position(),
- 210 "Parameter uses type parameter of unavailable type " + t.fullName() + " in "
- 211 + cl.qualifiedName() + "." + m.name() + "()");
- 212 }
- 213 }
- 214 }
- 215 }
- 216 }
- 217
- 218 // annotations are handled like methods
- 219 for (MethodInfo m : cl.annotationElements()) {
- 220 if (m.isHiddenOrRemoved()) {
- 221 Errors.error(Errors.UNAVAILABLE_SYMBOL, m.position(), "Reference to unavailable annotation "
- 222 + m.name());
- 223 }
- 224
- 225 ClassInfo returnClass = m.returnType().asClassInfo();
- 226 if (returnClass != null && returnClass.isHiddenOrRemoved()) {
- 227 Errors.error(Errors.UNAVAILABLE_SYMBOL, m.position(), "Annotation '" + m.name()
- 228 + "' returns unavailable type " + returnClass.name());
- 229 }
- 230
- 231 for (ParameterInfo p : m.parameters()) {
- 232 TypeInfo t = p.type();
- 233 if (!t.isPrimitive()) {
- 234 if (t.asClassInfo().isHiddenOrRemoved()) {
- 235 Errors.error(Errors.UNAVAILABLE_SYMBOL, p.position(),
- 236 "Reference to unavailable annotation class " + t.fullName());
- 237 }
- 238 }
- 239 }
- 240 }
- 241 } else if (cl.isDeprecated()) {
- 242 // not hidden, but deprecated
- 243 Errors.error(Errors.DEPRECATED, cl.position(), "Class " + cl.qualifiedName()
- 244 + " is deprecated");
- 245 }
- 246 }
- 247
- 248 // packages contains all the notStrippable classes mapped by their containing packages
- 249 HashMap<PackageInfo, List<ClassInfo>> packages = new HashMap<PackageInfo, List<ClassInfo>>();
- 250 final HashSet<Pattern> stubPackageWildcards = extractWildcards(stubPackages);
- 251 for (ClassInfo cl : notStrippable) {
- 252 if(cl.containingPackage().name().contains("android.car.xxxx.bt")){
- 253 System.out.println("=======android.car.xxxx.bt=============continue");
- 254 continue;
- 255 }
- 256 if (!cl.isDocOnly()) {
- 257 if (stubSourceOnly && !Files.exists(Paths.get(cl.position().file))) {
- 258 continue;
- 259 }
- 260 if (shouldWriteStub(cl.containingPackage().name(), stubPackages, stubPackageWildcards)) {
- 261 // write out the stubs
- 262 if (stubsDir != null) {
- 263 writeClassFile(stubsDir, notStrippable, cl);
- 264 }
- 265 // build class list for api file or keep list file
- 266 if (apiWriter != null || dexApiWriter != null || keepListWriter != null) {
- 267 if (packages.containsKey(cl.containingPackage())) {
- 268 packages.get(cl.containingPackage()).add(cl);
- 269 } else {
- 270 ArrayList<ClassInfo> classes = new ArrayList<ClassInfo>();
- 271 classes.add(cl);
- 272 packages.put(cl.containingPackage(), classes);
- 273 }
- 274 }
- 275 }
- 276 }
- 277 }
- 278
- 279 if (privateApiWriter != null || privateDexApiWriter != null || removedApiWriter != null
- 280 || removedDexApiWriter != null) {
- 281 allClassesByPackage = Converter.allClasses().stream()
- 282 // Make sure that the files only contains information from the required packages.
- 283 .filter(ci -> stubPackages == null
- 284 || stubPackages.contains(ci.containingPackage().qualifiedName()))
- 285 .collect(Collectors.groupingBy(ClassInfo::containingPackage));
- 286 }
- 287
- 288 final boolean ignoreShown = Doclava.showUnannotated;
- 289
- 290 Predicate<MemberInfo> memberIsNotCloned = (x -> !x.isCloned());
- 291
- 292 FilterPredicate apiFilter = new FilterPredicate(new ApiPredicate().setIgnoreShown(ignoreShown));
- 293 ApiPredicate apiReference = new ApiPredicate().setIgnoreShown(true);
- 294 Predicate<MemberInfo> apiEmit = apiFilter.and(new ElidingPredicate(apiReference));
- 295 Predicate<MemberInfo> dexApiEmit = memberIsNotCloned.and(apiFilter);
- 296
- 297 Predicate<MemberInfo> privateEmit = memberIsNotCloned.and(apiFilter.negate());
- 298 Predicate<MemberInfo> privateReference = (x -> true);
- 299
- 300 FilterPredicate removedFilter =
- 301 new FilterPredicate(new ApiPredicate().setIgnoreShown(ignoreShown).setMatchRemoved(true));
- 302 ApiPredicate removedReference = new ApiPredicate().setIgnoreShown(true).setIgnoreRemoved(true);
- 303 Predicate<MemberInfo> removedEmit = removedFilter.and(new ElidingPredicate(removedReference));
- 304 Predicate<MemberInfo> removedDexEmit = memberIsNotCloned.and(removedFilter);
- 305
- 306 // Write out the current API
- 307 if (apiWriter != null) {
- 308 writeApi(apiWriter, packages, apiEmit, apiReference);
- 309 apiWriter.close();
- 310 }
- 311
- 312 // Write out the current DEX API
- 313 if (dexApiWriter != null) {
- 314 writeDexApi(dexApiWriter, packages, dexApiEmit);
- 315 dexApiWriter.close();
- 316 }
- 317
- 318 // Write out the keep list
- 319 if (keepListWriter != null) {
- 320 writeKeepList(keepListWriter, packages, notStrippable);
- 321 keepListWriter.close();
- 322 }
- 323
- 324 // Write out the private API
- 325 if (privateApiWriter != null) {
- 326 writeApi(privateApiWriter, allClassesByPackage, privateEmit, privateReference);
- 327 privateApiWriter.close();
- 328 }
- 329
- 330 // Write out the private API
- 331 if (privateDexApiWriter != null) {
- 332 writeDexApi(privateDexApiWriter, allClassesByPackage, privateEmit);
- 333 privateDexApiWriter.close();
- 334 }
- 335
- 336 // Write out the removed API
- 337 if (removedApiWriter != null) {
- 338 writeApi(removedApiWriter, allClassesByPackage, removedEmit, removedReference);
- 339 removedApiWriter.close();
- 340 }
- 341
- 342 // Write out the removed DEX API
- 343 if (removedDexApiWriter != null) {
- 344 writeDexApi(removedDexApiWriter, allClassesByPackage, removedDexEmit);
- 345 removedDexApiWriter.close();
- 346 }
- 347 }
- 348
- 349 private static boolean shouldWriteStub(final String packageName,
- 350 final HashSet<String> stubPackages, final HashSet<Pattern> stubPackageWildcards) {
- 351 if (stubPackages == null) {
- 352 // There aren't any stub packages set, write all stubs
- 353 return true;
- 354 }
- 355 if (stubPackages.contains(packageName)) {
- 356 // Stub packages contains package, return true
- 357 return true;
- 358 }
- 359 if (stubPackageWildcards != null) {
- 360 // Else, we will iterate through the wildcards to see if there's a match
- 361 for (Pattern wildcard : stubPackageWildcards) {
- 362 if (wildcard.matcher(packageName).matches()) {
- 363 return true;
- 364 }
- 365 }
- 366 }
- 367 return false;
- 368 }
- 369
- 370 private static HashSet<Pattern> extractWildcards(HashSet<String> stubPackages) {
- 371 HashSet<Pattern> wildcards = null;
- 372 if (stubPackages != null) {
- 373 for (Iterator<String> i = stubPackages.iterator(); i.hasNext();) {
- 374 final String pkg = i.next();
- 375 if (pkg.indexOf('*') != -1) {
- 376 if (wildcards == null) {
- 377 wildcards = new HashSet<Pattern>();
- 378 }
- 379 // Add the compiled wildcard, replacing * with the regex equivalent
- 380 wildcards.add(Pattern.compile(pkg.replace("*", ".*?")));
- 381 // And remove the raw wildcard from the packages
- 382 i.remove();
- 383 }
- 384 }
- 385 }
- 386 return wildcards;
- 387 }
- 388
- 389 /**
- 390 * Find references to hidden classes.
- 391 *
- 392 * <p>This finds hidden classes that are used by public parts of the API in order to ensure the
- 393 * API is self consistent and does not reference classes that are not included in
- 394 * the stubs. Any such references cause an error to be reported.
- 395 *
- 396 * <p>A reference to an imported class is not treated as an error, even though imported classes
- 397 * are hidden from the stub generation. That is because imported classes are, by definition,
- 398 * excluded from the set of classes for which stubs are required.
- 399 *
- 400 * @param ti the type information to examine for references to hidden classes.
- 401 * @param stubImportPackages the possibly null set of imported package names.
- 402 * @return a reference to a hidden class or null if there are none
- 403 */
- 404 private static ClassInfo findHiddenClasses(TypeInfo ti, HashSet<String> stubImportPackages) {
- 405 ClassInfo ci = ti.asClassInfo();
- 406 if (ci == null) return null;
- 407 if (stubImportPackages != null
- 408 && stubImportPackages.contains(ci.containingPackage().qualifiedName())) {
- 409 return null;
- 410 }
- 411 if (ci.isHiddenOrRemoved()) return ci;
- 412 if (ti.typeArguments() != null) {
- 413 for (TypeInfo tii : ti.typeArguments()) {
- 414 // Avoid infinite recursion in the case of Foo<T extends Foo>
- 415 if (tii.qualifiedTypeName() != ti.qualifiedTypeName()) {
- 416 ClassInfo hiddenClass = findHiddenClasses(tii, stubImportPackages);
- 417 if (hiddenClass != null) return hiddenClass;
- 418 }
- 419 }
- 420 }
- 421 return null;
- 422 }
- 423
- 424 public static void cantStripThis(ClassInfo cl, HashSet<ClassInfo> notStrippable, String why,
- 425 HashSet<String> stubImportPackages) {
- 426
- 427 if (stubImportPackages != null
- 428 && stubImportPackages.contains(cl.containingPackage().qualifiedName())) {
- 429 // if the package is imported then it does not need stubbing.
- 430 return;
- 431 }
- 432
- 433 if (!notStrippable.add(cl)) {
- 434 // slight optimization: if it already contains cl, it already contains
- 435 // all of cl's parents
- 436 return;
- 437 }
- 438 cl.setReasonIncluded(why);
- 439
- 440 // cant strip annotations
- 441 /*
- 442 * if (cl.annotations() != null){ for (AnnotationInstanceInfo ai : cl.annotations()){ if
- 443 * (ai.type() != null){ cantStripThis(ai.type(), notStrippable, "1:" + cl.qualifiedName()); } }
- 444 * }
- 445 */
- 446 // cant strip any public fields or their generics
- 447 if (cl.selfFields() != null) {
- 448 for (FieldInfo fInfo : cl.selfFields()) {
- 449 if (fInfo.type() != null) {
- 450 if (fInfo.type().asClassInfo() != null) {
- 451 cantStripThis(fInfo.type().asClassInfo(), notStrippable, "2:" + cl.qualifiedName(),
- 452 stubImportPackages);
- 453 }
- 454 if (fInfo.type().typeArguments() != null) {
- 455 for (TypeInfo tTypeInfo : fInfo.type().typeArguments()) {
- 456 if (tTypeInfo.asClassInfo() != null) {
- 457 cantStripThis(tTypeInfo.asClassInfo(), notStrippable, "3:" + cl.qualifiedName(),
- 458 stubImportPackages);
- 459 }
- 460 }
- 461 }
- 462 }
- 463 }
- 464 }
- 465 // cant strip any of the type's generics
- 466 if (cl.asTypeInfo() != null) {
- 467 if (cl.asTypeInfo().typeArguments() != null) {
- 468 for (TypeInfo tInfo : cl.asTypeInfo().typeArguments()) {
- 469 if (tInfo.asClassInfo() != null) {
- 470 cantStripThis(tInfo.asClassInfo(), notStrippable, "4:" + cl.qualifiedName(),
- 471 stubImportPackages);
- 472 }
- 473 }
- 474 }
- 475 }
- 476 // cant strip any of the annotation elements
- 477 // cantStripThis(cl.annotationElements(), notStrippable);
- 478 // take care of methods
- 479 cantStripThis(cl.allSelfMethods(), notStrippable, stubImportPackages);
- 480 cantStripThis(cl.allConstructors(), notStrippable, stubImportPackages);
- 481 // blow the outer class open if this is an inner class
- 482 if (cl.containingClass() != null) {
- 483 cantStripThis(cl.containingClass(), notStrippable, "5:" + cl.qualifiedName(),
- 484 stubImportPackages);
- 485 }
- 486 // blow open super class and interfaces
- 487 ClassInfo supr = cl.realSuperclass();
- 488 if (supr != null) {
- 489 if (supr.isHiddenOrRemoved()) {
- 490 // cl is a public class declared as extending a hidden superclass.
- 491 // this is not a desired practice but it's happened, so we deal
- 492 // with it by finding the first super class which passes checklevel for purposes of
- 493 // generating the doc & stub information, and proceeding normally.
- 494 ClassInfo publicSuper = cl.superclass();
- 495 cl.init(cl.asTypeInfo(), cl.realInterfaces(), cl.realInterfaceTypes(), cl.innerClasses(),
- 496 cl.allConstructors(), cl.allSelfMethods(), cl.annotationElements(), cl.allSelfFields(),
- 497 cl.enumConstants(), cl.containingPackage(), cl.containingClass(),
- 498 publicSuper, publicSuper.asTypeInfo(), cl.annotations());
- 499 Errors.error(Errors.HIDDEN_SUPERCLASS, cl.position(), "Public class " + cl.qualifiedName()
- 500 + " stripped of unavailable superclass " + supr.qualifiedName());
- 501 } else {
- 502 cantStripThis(supr, notStrippable, "6:" + cl.realSuperclass().name() + cl.qualifiedName(),
- 503 stubImportPackages);
- 504 if (supr.isPrivate()) {
- 505 Errors.error(Errors.PRIVATE_SUPERCLASS, cl.position(), "Public class "
- 506 + cl.qualifiedName() + " extends private class " + supr.qualifiedName());
- 507 }
- 508 }
- 509 }
- 510 }
- 511
- 512 private static void cantStripThis(ArrayList<MethodInfo> mInfos, HashSet<ClassInfo> notStrippable,
- 513 HashSet<String> stubImportPackages) {
- 514 // for each method, blow open the parameters, throws and return types. also blow open their
- 515 // generics
- 516 if (mInfos != null) {
- 517 for (MethodInfo mInfo : mInfos) {
- 518 if (mInfo.getTypeParameters() != null) {
- 519 for (TypeInfo tInfo : mInfo.getTypeParameters()) {
- 520 if (tInfo.asClassInfo() != null) {
- 521 cantStripThis(tInfo.asClassInfo(), notStrippable, "8:"
- 522 + mInfo.realContainingClass().qualifiedName() + ":" + mInfo.name(),
- 523 stubImportPackages);
- 524 }
- 525 }
- 526 }
- 527 if (mInfo.parameters() != null) {
- 528 for (ParameterInfo pInfo : mInfo.parameters()) {
- 529 if (pInfo.type() != null && pInfo.type().asClassInfo() != null) {
- 530 cantStripThis(pInfo.type().asClassInfo(), notStrippable, "9:"
- 531 + mInfo.realContainingClass().qualifiedName() + ":" + mInfo.name(),
- 532 stubImportPackages);
- 533 if (pInfo.type().typeArguments() != null) {
- 534 for (TypeInfo tInfoType : pInfo.type().typeArguments()) {
- 535 if (tInfoType.asClassInfo() != null) {
- 536 ClassInfo tcl = tInfoType.asClassInfo();
- 537 if (tcl.isHiddenOrRemoved()) {
- 538 Errors
- 539 .error(Errors.UNAVAILABLE_SYMBOL, mInfo.position(),
- 540 "Parameter of hidden type " + tInfoType.fullName() + " in "
- 541 + mInfo.containingClass().qualifiedName() + '.' + mInfo.name()
- 542 + "()");
- 543 } else {
- 544 cantStripThis(tcl, notStrippable, "10:"
- 545 + mInfo.realContainingClass().qualifiedName() + ":" + mInfo.name(),
- 546 stubImportPackages);
- 547 }
- 548 }
- 549 }
- 550 }
- 551 }
- 552 }
- 553 }
- 554 for (ClassInfo thrown : mInfo.thrownExceptions()) {
- 555 cantStripThis(thrown, notStrippable, "11:" + mInfo.realContainingClass().qualifiedName()
- 556 + ":" + mInfo.name(), stubImportPackages);
- 557 }
- 558 if (mInfo.returnType() != null && mInfo.returnType().asClassInfo() != null) {
- 559 cantStripThis(mInfo.returnType().asClassInfo(), notStrippable, "12:"
- 560 + mInfo.realContainingClass().qualifiedName() + ":" + mInfo.name(),
- 561 stubImportPackages);
- 562 if (mInfo.returnType().typeArguments() != null) {
- 563 for (TypeInfo tyInfo : mInfo.returnType().typeArguments()) {
- 564 if (tyInfo.asClassInfo() != null) {
- 565 cantStripThis(tyInfo.asClassInfo(), notStrippable, "13:"
- 566 + mInfo.realContainingClass().qualifiedName() + ":" + mInfo.name(),
- 567 stubImportPackages);
- 568 }
- 569 }
- 570 }
- 571 }
- 572 }
- 573 }
- 574 }
- 575
- 576 static String javaFileName(ClassInfo cl) {
- 577 String dir = "";
- 578 PackageInfo pkg = cl.containingPackage();
- 579 if (pkg != null) {
- 580 dir = pkg.name();
- 581 dir = dir.replace('.', '/') + '/';
- 582 }
- 583 return dir + cl.name() + ".java";
- 584 }
- 585
- 586 static void writeClassFile(String stubsDir, HashSet<ClassInfo> notStrippable, ClassInfo cl) {
- 587 // inner classes are written by their containing class
- 588 if (cl.containingClass() != null) {
- 589 return;
- 590 }
- 591
- 592 // Work around the bogus "Array" class we invent for
- 593 // Arrays.copyOf's Class<? extends T[]> newType parameter. (http://b/2715505)
- 594 if (cl.containingPackage() != null
- 595 && cl.containingPackage().name().equals(PackageInfo.DEFAULT_PACKAGE)) {
- 596 return;
- 597 }
- 598
- 599 String filename = stubsDir + '/' + javaFileName(cl);
- 600 File file = new File(filename);
- 601 ClearPage.ensureDirectory(file);
- 602
- 603 PrintStream stream = null;
- 604 try {
- 605 stream = new PrintStream(new BufferedOutputStream(new FileOutputStream(file)));
- 606 writeClassFile(stream, notStrippable, cl);
- 607 } catch (FileNotFoundException e) {
- 608 System.err.println("error writing file: " + filename);
- 609 } finally {
- 610 if (stream != null) {
- 611 stream.close();
- 612 }
- 613 }
- 614 }
- 615
- 616 static void writeClassFile(PrintStream stream, HashSet<ClassInfo> notStrippable, ClassInfo cl) {
- 617 PackageInfo pkg = cl.containingPackage();
- 618 if (cl.containingClass() == null) {
- 619 stream.print(parseLicenseHeader(cl.position()));
- 620 }
- 621 if (pkg != null) {
- 622 stream.println("package " + pkg.name() + ";");
- 623 }
- 624 writeClass(stream, notStrippable, cl);
- 625 }
- 626
- 627 private static String parseLicenseHeader(/* @Nonnull */ SourcePositionInfo positionInfo) {
- 628 if (positionInfo == null) {
- 629 throw new NullPointerException("positionInfo == null");
- 630 }
- 631
- 632 try {
- 633 final File sourceFile = new File(positionInfo.file);
- 634 if (!sourceFile.exists()) {
- 635 throw new IllegalArgumentException("Unable to find " + sourceFile +
- 636 ". This is usually because doclava has been asked to generate stubs for a file " +
- 637 "that isn't present in the list of input source files but exists in the input " +
- 638 "classpath.");
- 639 }
- 640 return parseLicenseHeader(new FileInputStream(sourceFile));
- 641 } catch (IOException ioe) {
- 642 throw new RuntimeException("Unable to parse license header for: " + positionInfo.file, ioe);
- 643 }
- 644 }
- 645
- 646 /* @VisibleForTesting */
- 647 static String parseLicenseHeader(InputStream input) throws IOException {
- 648 StringBuilder builder = new StringBuilder(8192);
- 649 try (Scanner scanner = new Scanner(
- 650 new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8)))) {
- 651 String line;
- 652 while (scanner.hasNextLine()) {
- 653 line = scanner.nextLine().trim();
- 654 // Use an extremely simple strategy for parsing license headers : assume that
- 655 // all file content before the first "package " or "import " directive is a license
- 656 // header. In some cases this might contain more than just the license header, but we
- 657 // don't care.
- 658 if (line.startsWith("package ") || line.startsWith("import ")) {
- 659 break;
- 660 }
- 661 builder.append(line);
- 662 builder.append("\n");
- 663 }
- 664
- 665 // We've reached the end of the file without reaching any package or import
- 666 // directives.
- 667 if (!scanner.hasNextLine()) {
- 668 throw new IOException("Unable to parse license header");
- 669 }
- 670 }
- 671
- 672 return builder.toString();
- 673 }
- 674
- 675 static void writeClass(PrintStream stream, HashSet<ClassInfo> notStrippable, ClassInfo cl) {
- 676 writeAnnotations(stream, cl.annotations(), cl.isDeprecated());
- 677
- 678 stream.print(cl.scope() + " ");
- 679 if (cl.isAbstract() && !cl.isAnnotation() && !cl.isInterface()) {
- 680 stream.print("abstract ");
- 681 }
- 682 if (cl.isStatic()) {
- 683 stream.print("static ");
- 684 }
- 685 if (cl.isFinal() && !cl.isEnum()) {
- 686 stream.print("final ");
- 687 }
- 688 if (false) {
- 689 stream.print("strictfp ");
- 690 }
- 691
- 692 HashSet<String> classDeclTypeVars = new HashSet();
- 693 String leafName = cl.asTypeInfo().fullName(classDeclTypeVars);
- 694 int bracket = leafName.indexOf('<');
- 695 if (bracket < 0) bracket = leafName.length() - 1;
- 696 int period = leafName.lastIndexOf('.', bracket);
- 697 if (period < 0) period = -1;
- 698 leafName = leafName.substring(period + 1);
- 699
- 700 String kind = cl.kind();
- 701 stream.println(kind + " " + leafName);
- 702
- 703 TypeInfo base = cl.superclassType();
- 704
- 705 if (!"enum".equals(kind)) {
- 706 if (base != null && !"java.lang.Object".equals(base.qualifiedTypeName())) {
- 707 stream.println(" extends " + base.fullName(classDeclTypeVars));
- 708 }
- 709 }
- 710
- 711 List<TypeInfo> usedInterfaces = new ArrayList<TypeInfo>();
- 712 for (TypeInfo iface : cl.realInterfaceTypes()) {
- 713 if (notStrippable.contains(iface.asClassInfo()) && !iface.asClassInfo().isDocOnly()) {
- 714 usedInterfaces.add(iface);
- 715 }
- 716 }
- 717 if (usedInterfaces.size() > 0 && !cl.isAnnotation()) {
- 718 // can java annotations extend other ones?
- 719 if (cl.isInterface() || cl.isAnnotation()) {
- 720 stream.print(" extends ");
- 721 } else {
- 722 stream.print(" implements ");
- 723 }
- 724 String comma = "";
- 725 for (TypeInfo iface : usedInterfaces) {
- 726 stream.print(comma + iface.fullName(classDeclTypeVars));
- 727 comma = ", ";
- 728 }
- 729 stream.println();
- 730 }
- 731
- 732 stream.println("{");
- 733
- 734 ArrayList<FieldInfo> enumConstants = cl.enumConstants();
- 735 int N = enumConstants.size();
- 736 int i = 0;
- 737 for (FieldInfo field : enumConstants) {
- 738 writeAnnotations(stream, field.annotations(), field.isDeprecated());
- 739 if (!field.constantLiteralValue().equals("null")) {
- 740 stream.println(field.name() + "(" + field.constantLiteralValue()
- 741 + (i == N - 1 ? ");" : "),"));
- 742 } else {
- 743 stream.println(field.name() + "(" + (i == N - 1 ? ");" : "),"));
- 744 }
- 745 i++;
- 746 }
- 747
- 748 for (ClassInfo inner : cl.getRealInnerClasses()) {
- 749 if (notStrippable.contains(inner) && !inner.isDocOnly()) {
- 750 writeClass(stream, notStrippable, inner);
- 751 }
- 752 }
- 753
- 754
- 755 for (MethodInfo method : cl.constructors()) {
- 756 if (!method.isDocOnly()) {
- 757 writeMethod(stream, method, true);
- 758 }
- 759 }
- 760
- 761 boolean fieldNeedsInitialization = false;
- 762 boolean staticFieldNeedsInitialization = false;
- 763 for (FieldInfo field : cl.selfFields()) {
- 764 if (!field.isDocOnly()) {
- 765 if (!field.isStatic() && field.isFinal() && !fieldIsInitialized(field)) {
- 766 fieldNeedsInitialization = true;
- 767 }
- 768 if (field.isStatic() && field.isFinal() && !fieldIsInitialized(field)) {
- 769 staticFieldNeedsInitialization = true;
- 770 }
- 771 }
- 772 }
- 773
- 774 // The compiler includes a default public constructor that calls the super classes
- 775 // default constructor in the case where there are no written constructors.
- 776 // So, if we hide all the constructors, java may put in a constructor
- 777 // that calls a nonexistent super class constructor. So, if there are no constructors,
- 778 // and the super class doesn't have a default constructor, write in a private constructor
- 779 // that works. TODO -- we generate this as protected, but we really should generate
- 780 // it as private unless it also exists in the real code.
- 781 if ((cl.constructors().isEmpty() && (!cl.getNonWrittenConstructors().isEmpty() ||
- 782 fieldNeedsInitialization)) && !cl.isAnnotation() && !cl.isInterface() && !cl.isEnum()) {
- 783 // Errors.error(Errors.HIDDEN_CONSTRUCTOR,
- 784 // cl.position(), "No constructors " +
- 785 // "found and superclass has no parameterless constructor. A constructor " +
- 786 // "that calls an appropriate superclass constructor " +
- 787 // "was automatically written to stubs.\n");
- 788 stream.println(cl.leafName() + "() { " + superCtorCall(cl, null) + "throw new"
- 789 + " RuntimeException(\"Stub!\"); }");
- 790 }
- 791
- 792 for (MethodInfo method : cl.allSelfMethods()) {
- 793 if (cl.isEnum()) {
- 794 if (("values".equals(method.name()) && "()".equals(method.signature())) ||
- 795 ("valueOf".equals(method.name()) &&
- 796 "(java.lang.String)".equals(method.signature()))) {
- 797 // skip these two methods on enums, because they're synthetic,
- 798 // although for some reason javadoc doesn't mark them as synthetic,
- 799 // maybe because they still want them documented
- 800 continue;
- 801 }
- 802 }
- 803 if (!method.isDocOnly()) {
- 804 writeMethod(stream, method, false);
- 805 }
- 806 }
- 807 // Write all methods that are hidden or removed, but override abstract methods or interface methods.
- 808 // These can't be hidden.
- 809 List<MethodInfo> hiddenAndRemovedMethods = cl.getHiddenMethods();
- 810 hiddenAndRemovedMethods.addAll(cl.getRemovedMethods());
- 811 for (MethodInfo method : hiddenAndRemovedMethods) {
- 812 MethodInfo overriddenMethod =
- 813 method.findRealOverriddenMethod(method.name(), method.signature(), notStrippable);
- 814 ClassInfo classContainingMethod =
- 815 method.findRealOverriddenClass(method.name(), method.signature());
- 816 if (overriddenMethod != null && !overriddenMethod.isHiddenOrRemoved() &&
- 817 !overriddenMethod.isDocOnly() &&
- 818 (overriddenMethod.isAbstract() || overriddenMethod.containingClass().isInterface())) {
- 819 method.setReason("1:" + classContainingMethod.qualifiedName());
- 820 cl.addMethod(method);
- 821 writeMethod(stream, method, false);
- 822 }
- 823 }
- 824
- 825 for (MethodInfo element : cl.annotationElements()) {
- 826 if (!element.isDocOnly()) {
- 827 writeAnnotationElement(stream, element);
- 828 }
- 829 }
- 830
- 831 for (FieldInfo field : cl.selfFields()) {
- 832 if (!field.isDocOnly()) {
- 833 writeField(stream, field);
- 834 }
- 835 }
- 836
- 837 if (staticFieldNeedsInitialization) {
- 838 stream.print("static { ");
- 839 for (FieldInfo field : cl.selfFields()) {
- 840 if (!field.isDocOnly() && field.isStatic() && field.isFinal() && !fieldIsInitialized(field)
- 841 && field.constantValue() == null) {
- 842 stream.print(field.name() + " = " + field.type().defaultValue() + "; ");
- 843 }
- 844 }
- 845 stream.println("}");
- 846 }
- 847
- 848 stream.println("}");
- 849 }
- 850
- 851 static void writeMethod(PrintStream stream, MethodInfo method, boolean isConstructor) {
- 852 String comma;
- 853
- 854 writeAnnotations(stream, method.annotations(), method.isDeprecated());
- 855
- 856 if (method.isDefault()) {
- 857 stream.print("default ");
- 858 }
- 859 stream.print(method.scope() + " ");
- 860 if (method.isStatic()) {
- 861 stream.print("static ");
- 862 }
- 863 if (method.isFinal()) {
- 864 stream.print("final ");
- 865 }
- 866 if (method.isAbstract()) {
- 867 stream.print("abstract ");
- 868 }
- 869 if (method.isSynchronized()) {
- 870 stream.print("synchronized ");
- 871 }
- 872 if (method.isNative()) {
- 873 stream.print("native ");
- 874 }
- 875 if (false /* method.isStictFP() */) {
- 876 stream.print("strictfp ");
- 877 }
- 878
- 879 stream.print(method.typeArgumentsName(new HashSet()) + " ");
- 880
- 881 if (!isConstructor) {
- 882 stream.print(method.returnType().fullName(method.typeVariables()) + " ");
- 883 }
- 884 String n = method.name();
- 885 int pos = n.lastIndexOf('.');
- 886 if (pos >= 0) {
- 887 n = n.substring(pos + 1);
- 888 }
- 889 stream.print(n + "(");
- 890 comma = "";
- 891 int count = 1;
- 892 int size = method.parameters().size();
- 893 for (ParameterInfo param : method.parameters()) {
- 894 stream.print(comma);
- 895 writeAnnotations(stream, param.annotations(), false);
- 896 stream.print(fullParameterTypeName(method, param.type(), count == size) + " "
- 897 + param.name());
- 898 comma = ", ";
- 899 count++;
- 900 }
- 901 stream.print(")");
- 902
- 903 comma = "";
- 904 if (method.thrownExceptions().size() > 0) {
- 905 stream.print(" throws ");
- 906 for (ClassInfo thrown : method.thrownExceptions()) {
- 907 stream.print(comma + thrown.qualifiedName());
- 908 comma = ", ";
- 909 }
- 910 }
- 911 if (method.isAbstract() || method.isNative() || (method.containingClass().isInterface() && (!method.isDefault() && !method.isStatic()))) {
- 912 stream.println(";");
- 913 } else {
- 914 stream.print(" { ");
- 915 if (isConstructor) {
- 916 stream.print(superCtorCall(method.containingClass(), method.thrownExceptions()));
- 917 }
- 918 stream.println("throw new RuntimeException(\"Stub!\"); }");
- 919 }
- 920 }
- 921
- 922 static void writeField(PrintStream stream, FieldInfo field) {
- 923 writeAnnotations(stream, field.annotations(), field.isDeprecated());
- 924
- 925 stream.print(field.scope() + " ");
- 926 if (field.isStatic()) {
- 927 stream.print("static ");
- 928 }
- 929 if (field.isFinal()) {
- 930 stream.print("final ");
- 931 }
- 932 if (field.isTransient()) {
- 933 stream.print("transient ");
- 934 }
- 935 if (field.isVolatile()) {
- 936 stream.print("volatile ");
- 937 }
- 938
- 939 stream.print(field.type().fullName());
- 940 stream.print(" ");
- 941 stream.print(field.name());
- 942
- 943 if (fieldIsInitialized(field)) {
- 944 stream.print(" = " + field.constantLiteralValue());
- 945 }
- 946
- 947 stream.println(";");
- 948 }
- 949
- 950 static boolean fieldIsInitialized(FieldInfo field) {
- 951 return (field.isFinal() && field.constantValue() != null)
- 952 || !field.type().dimension().equals("") || field.containingClass().isInterface();
- 953 }
- 954
- 955 static boolean canCallMethod(ClassInfo from, MethodInfo m) {
- 956 if (m.isPublic() || m.isProtected()) {
- 957 return true;
- 958 }
- 959 if (m.isPackagePrivate()) {
- 960 String fromPkg = from.containingPackage().name();
- 961 String pkg = m.containingClass().containingPackage().name();
- 962 if (fromPkg.equals(pkg)) {
- 963 return true;
- 964 }
- 965 }
- 966 return false;
- 967 }
- 968
- 969 // call a constructor, any constructor on this class's superclass.
- 970 static String superCtorCall(ClassInfo cl, ArrayList<ClassInfo> thrownExceptions) {
- 971 ClassInfo base = cl.realSuperclass();
- 972 if (base == null) {
- 973 return "";
- 974 }
- 975 HashSet<String> exceptionNames = new HashSet<String>();
- 976 if (thrownExceptions != null) {
- 977 for (ClassInfo thrown : thrownExceptions) {
- 978 exceptionNames.add(thrown.name());
- 979 }
- 980 }
- 981 ArrayList<MethodInfo> ctors = base.constructors();
- 982 MethodInfo ctor = null;
- 983 // bad exception indicates that the exceptions thrown by the super constructor
- 984 // are incompatible with the constructor we're using for the sub class.
- 985 Boolean badException = false;
- 986 for (MethodInfo m : ctors) {
- 987 if (canCallMethod(cl, m)) {
- 988 if (m.thrownExceptions() != null) {
- 989 for (ClassInfo thrown : m.thrownExceptions()) {
- 990 if (thrownExceptions != null && !exceptionNames.contains(thrown.name())) {
- 991 badException = true;
- 992 }
- 993 }
- 994 }
- 995 if (badException) {
- 996 badException = false;
- 997 continue;
- 998 }
- 999 // if it has no args, we're done
- 1000 if (m.parameters().isEmpty()) {
- 1001 return "";
- 1002 }
- 1003 ctor = m;
- 1004 }
- 1005 }
- 1006 if (ctor != null) {
- 1007 String result = "";
- 1008 result += "super(";
- 1009 ArrayList<ParameterInfo> params = ctor.parameters();
- 1010 for (ParameterInfo param : params) {
- 1011 TypeInfo t = param.type();
- 1012 if (t.isPrimitive() && t.dimension().equals("")) {
- 1013 String n = t.simpleTypeName();
- 1014 if (("byte".equals(n) || "short".equals(n) || "int".equals(n) || "long".equals(n)
- 1015 || "float".equals(n) || "double".equals(n))
- 1016 && t.dimension().equals("")) {
- 1017 result += "0";
- 1018 } else if ("char".equals(n)) {
- 1019 result += "'\\0'";
- 1020 } else if ("boolean".equals(n)) {
- 1021 result += "false";
- 1022 } else {
- 1023 result += "<<unknown-" + n + ">>";
- 1024 }
- 1025 } else {
- 1026 // put null in each super class method. Cast null to the correct type
- 1027 // to avoid collisions with other constructors. If the type is generic
- 1028 // don't cast it
- 1029 result +=
- 1030 (!t.isTypeVariable() ? "(" + t.qualifiedTypeName() + t.dimension() + ")" : "")
- 1031 + "null";
- 1032 }
- 1033 if (param != params.get(params.size()-1)) {
- 1034 result += ",";
- 1035 }
- 1036 }
- 1037 result += "); ";
- 1038 return result;
- 1039 } else {
- 1040 return "";
- 1041 }
- 1042 }
- 1043
- 1044 /**
- 1045 * Write out the given list of annotations. If the {@code isDeprecated}
- 1046 * flag is true also write out a {@code @Deprecated} annotation if it did not
- 1047 * already appear in the list of annotations. (This covers APIs that mention
- 1048 * {@code @deprecated} in their documentation but fail to add
- 1049 * {@code @Deprecated} as an annotation.
- 1050 * <p>
- 1051 * {@code @Override} annotations are deliberately skipped.
- 1052 */
- 1053 static void writeAnnotations(PrintStream stream, List<AnnotationInstanceInfo> annotations,
- 1054 boolean isDeprecated) {
- 1055 assert annotations != null;
- 1056 for (AnnotationInstanceInfo ann : annotations) {
- 1057 // Skip @Override annotations: the stubs do not need it and in some cases it leads
- 1058 // to compilation errors with the way the stubs are generated
- 1059 if (ann.type() != null && ann.type().qualifiedName().equals("java.lang.Override")) {
- 1060 continue;
- 1061 }
- 1062 if (!ann.type().isHiddenOrRemoved()) {
- 1063 stream.println(ann.toString());
- 1064 if (isDeprecated && ann.type() != null
- 1065 && ann.type().qualifiedName().equals("java.lang.Deprecated")) {
- 1066 isDeprecated = false; // Prevent duplicate annotations
- 1067 }
- 1068 }
- 1069 }
- 1070 if (isDeprecated) {
- 1071 stream.println("@Deprecated");
- 1072 }
- 1073 }
- 1074
- 1075 static void writeAnnotationElement(PrintStream stream, MethodInfo ann) {
- 1076 stream.print(ann.returnType().fullName());
- 1077 stream.print(" ");
- 1078 stream.print(ann.name());
- 1079 stream.print("()");
- 1080 AnnotationValueInfo def = ann.defaultAnnotationElementValue();
- 1081 if (def != null) {
- 1082 stream.print(" default ");
- 1083 stream.print(def.valueString());
- 1084 }
- 1085 stream.println(";");
- 1086 }
- 1087
- 1088 public static void writeXml(PrintStream xmlWriter, Collection<PackageInfo> pkgs, boolean strip) {
- 1089 if (strip) {
- 1090 Stubs.writeXml(xmlWriter, pkgs);
- 1091 } else {
- 1092 Stubs.writeXml(xmlWriter, pkgs, c -> true);
- 1093 }
- 1094 }
- 1095
- 1096 public static void writeXml(PrintStream xmlWriter, Collection<PackageInfo> pkgs,
- 1097 Predicate<ClassInfo> notStrippable) {
- 1098
- 1099 final PackageInfo[] packages = pkgs.toArray(new PackageInfo[pkgs.size()]);
- 1100 Arrays.sort(packages, PackageInfo.comparator);
- 1101
- 1102 xmlWriter.println("<api>");
- 1103 for (PackageInfo pkg: packages) {
- 1104 writePackageXML(xmlWriter, pkg, pkg.allClasses().values(), notStrippable);
- 1105 }
- 1106 xmlWriter.println("</api>");
- 1107 }
- 1108
- 1109 public static void writeXml(PrintStream xmlWriter, Collection<PackageInfo> pkgs) {
- 1110 HashSet<ClassInfo> allClasses = new HashSet<>();
- 1111 for (PackageInfo pkg: pkgs) {
- 1112 allClasses.addAll(pkg.allClasses().values());
- 1113 }
- 1114 Predicate<ClassInfo> notStrippable = allClasses::contains;
- 1115 writeXml(xmlWriter, pkgs, notStrippable);
- 1116 }
- 1117
- 1118 static void writePackageXML(PrintStream xmlWriter, PackageInfo pack,
- 1119 Collection<ClassInfo> classList, Predicate<ClassInfo> notStrippable) {
- 1120 ClassInfo[] classes = classList.toArray(new ClassInfo[classList.size()]);
- 1121 Arrays.sort(classes, ClassInfo.comparator);
- 1122 // Work around the bogus "Array" class we invent for
- 1123 // Arrays.copyOf's Class<? extends T[]> newType parameter. (http://b/2715505)
- 1124 if (pack.name().equals(PackageInfo.DEFAULT_PACKAGE)) {
- 1125 return;
- 1126 }
- 1127 xmlWriter.println("<package name=\"" + pack.name() + "\"\n"
- 1128 // + " source=\"" + pack.position() + "\"\n"
- 1129 + ">");
- 1130 for (ClassInfo cl : classes) {
- 1131 writeClassXML(xmlWriter, cl, notStrippable);
- 1132 }
- 1133 xmlWriter.println("</package>");
- 1134
- 1135
- 1136 }
- 1137
- 1138 static void writeClassXML(PrintStream xmlWriter, ClassInfo cl, Predicate<ClassInfo> notStrippable) {
- 1139 String scope = cl.scope();
- 1140 String deprecatedString = "";
- 1141 String declString = (cl.isInterface()) ? "interface" : "class";
- 1142 if (cl.isDeprecated()) {
- 1143 deprecatedString = "deprecated";
- 1144 } else {
- 1145 deprecatedString = "not deprecated";
- 1146 }
- 1147 xmlWriter.println("<" + declString + " name=\"" + cl.name() + "\"");
- 1148 if (!cl.isInterface() && !cl.qualifiedName().equals("java.lang.Object")) {
- 1149 xmlWriter.println(" extends=\""
- 1150 + ((cl.realSuperclass() == null) ? "java.lang.Object" : cl.realSuperclass()
- 1151 .qualifiedName()) + "\"");
- 1152 }
- 1153 xmlWriter.println(" abstract=\"" + cl.isAbstract() + "\"\n" + " static=\"" + cl.isStatic()
- 1154 + "\"\n" + " final=\"" + cl.isFinal() + "\"\n" + " deprecated=\"" + deprecatedString
- 1155 + "\"\n" + " visibility=\"" + scope + "\"\n"
- 1156 // + " source=\"" + cl.position() + "\"\n"
- 1157 + ">");
- 1158
- 1159 ArrayList<ClassInfo> interfaces = cl.realInterfaces();
- 1160 Collections.sort(interfaces, ClassInfo.comparator);
- 1161 for (ClassInfo iface : interfaces) {
- 1162 if (notStrippable.test(iface)) {
- 1163 xmlWriter.println("<implements name=\"" + iface.qualifiedName() + "\">");
- 1164 xmlWriter.println("</implements>");
- 1165 }
- 1166 }
- 1167
- 1168 ArrayList<MethodInfo> constructors = cl.constructors();
- 1169 Collections.sort(constructors, MethodInfo.comparator);
- 1170 for (MethodInfo mi : constructors) {
- 1171 writeConstructorXML(xmlWriter, mi);
- 1172 }
- 1173
- 1174 ArrayList<MethodInfo> methods = cl.allSelfMethods();
- 1175 Collections.sort(methods, MethodInfo.comparator);
- 1176 for (MethodInfo mi : methods) {
- 1177 writeMethodXML(xmlWriter, mi);
- 1178 }
- 1179
- 1180 ArrayList<FieldInfo> fields = cl.selfFields();
- 1181 Collections.sort(fields, FieldInfo.comparator);
- 1182 for (FieldInfo fi : fields) {
- 1183 writeFieldXML(xmlWriter, fi);
- 1184 }
- 1185 xmlWriter.println("</" + declString + ">");
- 1186
- 1187 }
- 1188
- 1189 static void writeMethodXML(PrintStream xmlWriter, MethodInfo mi) {
- 1190 String scope = mi.scope();
- 1191
- 1192 String deprecatedString = "";
- 1193 if (mi.isDeprecated()) {
- 1194 deprecatedString = "deprecated";
- 1195 } else {
- 1196 deprecatedString = "not deprecated";
- 1197 }
- 1198 xmlWriter.println("<method name=\""
- 1199 + mi.name()
- 1200 + "\"\n"
- 1201 + ((mi.returnType() != null) ? " return=\""
- 1202 + makeXMLcompliant(fullParameterTypeName(mi, mi.returnType(), false)) + "\"\n" : "")
- 1203 + " abstract=\"" + mi.isAbstract() + "\"\n" + " native=\"" + mi.isNative() + "\"\n"
- 1204 + " synchronized=\"" + mi.isSynchronized() + "\"\n" + " static=\"" + mi.isStatic() + "\"\n"
- 1205 + " final=\"" + mi.isFinal() + "\"\n" + " deprecated=\"" + deprecatedString + "\"\n"
- 1206 + " visibility=\"" + scope + "\"\n"
- 1207 // + " source=\"" + mi.position() + "\"\n"
- 1208 + ">");
- 1209
- 1210 // write parameters in declaration order
- 1211 int numParameters = mi.parameters().size();
- 1212 int count = 0;
- 1213 for (ParameterInfo pi : mi.parameters()) {
- 1214 count++;
- 1215 writeParameterXML(xmlWriter, mi, pi, count == numParameters);
- 1216 }
- 1217
- 1218 // but write exceptions in canonicalized order
- 1219 ArrayList<ClassInfo> exceptions = mi.thrownExceptions();
- 1220 Collections.sort(exceptions, ClassInfo.comparator);
- 1221 for (ClassInfo pi : exceptions) {
- 1222 xmlWriter.println("<exception name=\"" + pi.name() + "\" type=\"" + pi.qualifiedName()
- 1223 + "\">");
- 1224 xmlWriter.println("</exception>");
- 1225 }
- 1226 xmlWriter.println("</method>");
- 1227 }
- 1228
- 1229 static void writeConstructorXML(PrintStream xmlWriter, MethodInfo mi) {
- 1230 String scope = mi.scope();
- 1231 String deprecatedString = "";
- 1232 if (mi.isDeprecated()) {
- 1233 deprecatedString = "deprecated";
- 1234 } else {
- 1235 deprecatedString = "not deprecated";
- 1236 }
- 1237 xmlWriter.println("<constructor name=\"" + mi.name() + "\"\n" + " type=\""
- 1238 + mi.containingClass().qualifiedName() + "\"\n" + " static=\"" + mi.isStatic() + "\"\n"
- 1239 + " final=\"" + mi.isFinal() + "\"\n" + " deprecated=\"" + deprecatedString + "\"\n"
- 1240 + " visibility=\"" + scope + "\"\n"
- 1241 // + " source=\"" + mi.position() + "\"\n"
- 1242 + ">");
- 1243
- 1244 int numParameters = mi.parameters().size();
- 1245 int count = 0;
- 1246 for (ParameterInfo pi : mi.parameters()) {
- 1247 count++;
- 1248 writeParameterXML(xmlWriter, mi, pi, count == numParameters);
- 1249 }
- 1250
- 1251 ArrayList<ClassInfo> exceptions = mi.thrownExceptions();
- 1252 Collections.sort(exceptions, ClassInfo.comparator);
- 1253 for (ClassInfo pi : exceptions) {
- 1254 xmlWriter.println("<exception name=\"" + pi.name() + "\" type=\"" + pi.qualifiedName()
- 1255 + "\">");
- 1256 xmlWriter.println("</exception>");
- 1257 }
- 1258 xmlWriter.println("</constructor>");
- 1259 }
- 1260
- 1261 static void writeParameterXML(PrintStream xmlWriter, MethodInfo method, ParameterInfo pi,
- 1262 boolean isLast) {
- 1263 xmlWriter.println("<parameter name=\"" + pi.name() + "\" type=\""
- 1264 + makeXMLcompliant(fullParameterTypeName(method, pi.type(), isLast)) + "\">");
- 1265 xmlWriter.println("</parameter>");
- 1266 }
- 1267
- 1268 static void writeFieldXML(PrintStream xmlWriter, FieldInfo fi) {
- 1269 String scope = fi.scope();
- 1270 String deprecatedString = "";
- 1271 if (fi.isDeprecated()) {
- 1272 deprecatedString = "deprecated";
- 1273 } else {
- 1274 deprecatedString = "not deprecated";
- 1275 }
- 1276 // need to make sure value is valid XML
- 1277 String value = makeXMLcompliant(fi.constantLiteralValue());
- 1278
- 1279 String fullTypeName = makeXMLcompliant(fi.type().fullName());
- 1280
- 1281 xmlWriter.println("<field name=\"" + fi.name() + "\"\n" + " type=\"" + fullTypeName + "\"\n"
- 1282 + " transient=\"" + fi.isTransient() + "\"\n" + " volatile=\"" + fi.isVolatile() + "\"\n"
- 1283 + (fieldIsInitialized(fi) ? " value=\"" + value + "\"\n" : "") + " static=\""
- 1284 + fi.isStatic() + "\"\n" + " final=\"" + fi.isFinal() + "\"\n" + " deprecated=\""
- 1285 + deprecatedString + "\"\n" + " visibility=\"" + scope + "\"\n"
- 1286 // + " source=\"" + fi.position() + "\"\n"
- 1287 + ">");
- 1288 xmlWriter.println("</field>");
- 1289 }
- 1290
- 1291 static String makeXMLcompliant(String s) {
- 1292 String returnString = "";
- 1293 returnString = s.replaceAll("&", "&");
- 1294 returnString = returnString.replaceAll("<", "<");
- 1295 returnString = returnString.replaceAll(">", ">");
- 1296 returnString = returnString.replaceAll("\"", """);
- 1297 returnString = returnString.replaceAll("'", "'");
- 1298 return returnString;
- 1299 }
- 1300
- 1301 /**
- 1302 * Predicate that decides if the given member should be considered part of an
- 1303 * API surface area. To make the most accurate decision, it searches for
- 1304 * signals on the member, all containing classes, and all containing packages.
- 1305 */
- 1306 public static class ApiPredicate implements Predicate<MemberInfo> {
- 1307 public boolean ignoreShown;
- 1308 public boolean ignoreRemoved;
- 1309 public boolean matchRemoved;
- 1310
- 1311 /**
- 1312 * Set if the value of {@link MemberInfo#hasShowAnnotation()} should be
- 1313 * ignored. That is, this predicate will assume that all encountered members
- 1314 * match the "shown" requirement.
- 1315 * <p>
- 1316 * This is typically useful when generating "current.txt", when no
- 1317 * {@link Doclava#showAnnotations} have been defined.
- 1318 */
- 1319 public ApiPredicate setIgnoreShown(boolean ignoreShown) {
- 1320 this.ignoreShown = ignoreShown;
- 1321 return this;
- 1322 }
- 1323
- 1324 /**
- 1325 * Set if the value of {@link MemberInfo#isRemoved()} should be ignored.
- 1326 * That is, this predicate will assume that all encountered members match
- 1327 * the "removed" requirement.
- 1328 * <p>
- 1329 * This is typically useful when generating "removed.txt", when it's okay to
- 1330 * reference both current and removed APIs.
- 1331 */
- 1332 public ApiPredicate setIgnoreRemoved(boolean ignoreRemoved) {
- 1333 this.ignoreRemoved = ignoreRemoved;
- 1334 return this;
- 1335 }
- 1336
- 1337 /**
- 1338 * Set what the value of {@link MemberInfo#isRemoved()} must be equal to in
- 1339 * order for a member to match.
- 1340 * <p>
- 1341 * This is typically useful when generating "removed.txt", when you only
- 1342 * want to match members that have actually been removed.
- 1343 */
- 1344 public ApiPredicate setMatchRemoved(boolean matchRemoved) {
- 1345 this.matchRemoved = matchRemoved;
- 1346 return this;
- 1347 }
- 1348
- 1349 private static PackageInfo containingPackage(PackageInfo pkg) {
- 1350 String name = pkg.name();
- 1351 final int lastDot = name.lastIndexOf('.');
- 1352 if (lastDot == -1) {
- 1353 return null;
- 1354 } else {
- 1355 name = name.substring(0, lastDot);
- 1356 return Converter.obtainPackage(name);
- 1357 }
- 1358 }
- 1359
- 1360 @Override
- 1361 public boolean test(MemberInfo member) {
- 1362 boolean visible = member.isPublic() || member.isProtected();
- 1363 boolean hasShowAnnotation = member.hasShowAnnotation();
- 1364 boolean hidden = member.isHidden();
- 1365 boolean docOnly = member.isDocOnly();
- 1366 boolean removed = member.isRemoved();
- 1367
- 1368 ClassInfo clazz = member.containingClass();
- 1369 if (clazz != null) {
- 1370 PackageInfo pkg = clazz.containingPackage();
- 1371 while (pkg != null) {
- 1372 hidden |= pkg.isHidden();
- 1373 docOnly |= pkg.isDocOnly();
- 1374 removed |= pkg.isRemoved();
- 1375 pkg = containingPackage(pkg);
- 1376 }
- 1377 }
- 1378 while (clazz != null) {
- 1379 visible &= clazz.isPublic() || clazz.isProtected();
- 1380 hasShowAnnotation |= clazz.hasShowAnnotation();
- 1381 hidden |= clazz.isHidden();
- 1382 docOnly |= clazz.isDocOnly();
- 1383 removed |= clazz.isRemoved();
- 1384 clazz = clazz.containingClass();
- 1385 }
- 1386
- 1387 if (ignoreShown) {
- 1388 hasShowAnnotation = true;
- 1389 }
- 1390 if (ignoreRemoved) {
- 1391 removed = matchRemoved;
- 1392 }
- 1393
- 1394 return visible && hasShowAnnotation && !hidden && !docOnly && (removed == matchRemoved);
- 1395 }
- 1396 }
- 1397
- 1398 /**
- 1399 * Filter that will elide exact duplicate members that are already included
- 1400 * in another superclass/interfaces.
- 1401 */
- 1402 public static class ElidingPredicate implements Predicate<MemberInfo> {
- 1403 private final Predicate<MemberInfo> wrapped;
- 1404
- 1405 public ElidingPredicate(Predicate<MemberInfo> wrapped) {
- 1406 this.wrapped = wrapped;
- 1407 }
- 1408
- 1409 @Override
- 1410 public boolean test(MemberInfo member) {
- 1411 // This member should be included, but if it's an exact duplicate
- 1412 // override then we can elide it.
- 1413 if (member instanceof MethodInfo) {
- 1414 MethodInfo method = (MethodInfo) member;
- 1415 if (method.returnType() != null) { // not a constructor
- 1416 String methodRaw = writeMethodApiWithoutDefault(method);
- 1417 return (method.findPredicateOverriddenMethod(new Predicate<MemberInfo>() {
- 1418 @Override
- 1419 public boolean test(MemberInfo test) {
- 1420 // We're looking for included and perfect signature
- 1421 return (wrapped.test(test)
- 1422 && writeMethodApiWithoutDefault((MethodInfo) test).equals(methodRaw));
- 1423 }
- 1424 }) == null);
- 1425 }
- 1426 }
- 1427 return true;
- 1428 }
- 1429 }
- 1430
- 1431 public static class FilterPredicate implements Predicate<MemberInfo> {
- 1432 private final Predicate<MemberInfo> wrapped;
- 1433
- 1434 public FilterPredicate(Predicate<MemberInfo> wrapped) {
- 1435 this.wrapped = wrapped;
- 1436 }
- 1437
- 1438 @Override
- 1439 public boolean test(MemberInfo member) {
- 1440 if (wrapped.test(member)) {
- 1441 return true;
- 1442 } else if (member instanceof MethodInfo) {
- 1443 MethodInfo method = (MethodInfo) member;
- 1444 return method.returnType() != null && // not a constructor
- 1445 method.findPredicateOverriddenMethod(wrapped) != null;
- 1446 } else {
- 1447 return false;
- 1448 }
- 1449 }
- 1450 }
- 1451
- 1452 static void writeApi(PrintStream apiWriter, Map<PackageInfo, List<ClassInfo>> classesByPackage,
- 1453 Predicate<MemberInfo> filterEmit, Predicate<MemberInfo> filterReference) {
- 1454 for (PackageInfo pkg : classesByPackage.keySet().stream().sorted(PackageInfo.comparator)
- 1455 .collect(Collectors.toList())) {
- 1456 if (pkg.name().equals(PackageInfo.DEFAULT_PACKAGE)) continue;
- 1457
- 1458 boolean hasWrittenPackageHead = false;
- 1459 for (ClassInfo clazz : classesByPackage.get(pkg).stream().sorted(ClassInfo.comparator)
- 1460 .collect(Collectors.toList())) {
- 1461 hasWrittenPackageHead = writeClassApi(apiWriter, clazz, filterEmit, filterReference,
- 1462 hasWrittenPackageHead);
- 1463 }
- 1464
- 1465 if (hasWrittenPackageHead) {
- 1466 apiWriter.print("}\n\n");
- 1467 }
- 1468 }
- 1469 }
- 1470
- 1471 static void writeDexApi(PrintStream apiWriter, Map<PackageInfo, List<ClassInfo>> classesByPackage,
- 1472 Predicate<MemberInfo> filterEmit) {
- 1473 for (PackageInfo pkg : classesByPackage.keySet().stream().sorted(PackageInfo.comparator)
- 1474 .collect(Collectors.toList())) {
- 1475 if (pkg.name().equals(PackageInfo.DEFAULT_PACKAGE)) continue;
- 1476
- 1477 for (ClassInfo clazz : classesByPackage.get(pkg).stream().sorted(ClassInfo.comparator)
- 1478 .collect(Collectors.toList())) {
- 1479 writeClassDexApi(apiWriter, clazz, filterEmit);
- 1480 }
- 1481 }
- 1482 }
- 1483
- 1484 /**
- 1485 * Write the removed members of the class to removed.txt
- 1486 */
- 1487 private static boolean writeClassApi(PrintStream apiWriter, ClassInfo cl,
- 1488 Predicate<MemberInfo> filterEmit, Predicate<MemberInfo> filterReference,
- 1489 boolean hasWrittenPackageHead) {
- 1490
- 1491 List<MethodInfo> constructors = cl.getExhaustiveConstructors().stream().filter(filterEmit)
- 1492 .sorted(MethodInfo.comparator).collect(Collectors.toList());
- 1493 List<MethodInfo> methods = cl.getExhaustiveMethods().stream().filter(filterEmit)
- 1494 .sorted(MethodInfo.comparator).collect(Collectors.toList());
- 1495 List<FieldInfo> enums = cl.getExhaustiveEnumConstants().stream().filter(filterEmit)
- 1496 .sorted(FieldInfo.comparator).collect(Collectors.toList());
- 1497 List<FieldInfo> fields = cl.filteredFields(filterEmit).stream()
- 1498 .sorted(FieldInfo.comparator).collect(Collectors.toList());
- 1499
- 1500 final boolean classEmpty = (constructors.isEmpty() && methods.isEmpty() && enums.isEmpty()
- 1501 && fields.isEmpty());
- 1502 final boolean emit;
- 1503 if (filterEmit.test(cl.asMemberInfo())) {
- 1504 emit = true;
- 1505 } else if (!classEmpty) {
- 1506 emit = filterReference.test(cl.asMemberInfo());
- 1507 } else {
- 1508 emit = false;
- 1509 }
- 1510 if (!emit) {
- 1511 return hasWrittenPackageHead;
- 1512 }
- 1513
- 1514 // Look for Android @SystemApi exposed outside the normal SDK; we require
- 1515 // that they're protected with a system permission.
- 1516 if (Doclava.android && Doclava.showAnnotations.contains("android.annotation.SystemApi")) {
- 1517 boolean systemService = "android.content.pm.PackageManager".equals(cl.qualifiedName());
- 1518 for (AnnotationInstanceInfo a : cl.annotations()) {
- 1519 if (a.type().qualifiedNameMatches("android", "annotation.SystemService")) {
- 1520 systemService = true;
- 1521 }
- 1522 }
- 1523 if (systemService) {
- 1524 for (MethodInfo mi : methods) {
- 1525 checkSystemPermissions(mi);
- 1526 }
- 1527 }
- 1528 }
- 1529
- 1530 for (MethodInfo method : methods) {
- 1531 checkHiddenTypes(method, filterReference);
- 1532 }
- 1533 for (FieldInfo field : fields) {
- 1534 checkHiddenTypes(field, filterReference);
- 1535 }
- 1536
- 1537 if (!hasWrittenPackageHead) {
- 1538 hasWrittenPackageHead = true;
- 1539 apiWriter.print("package ");
- 1540 apiWriter.print(cl.containingPackage().qualifiedName());
- 1541 apiWriter.print(" {\n\n");
- 1542 }
- 1543
- 1544 apiWriter.print(" ");
- 1545 apiWriter.print(cl.scope());
- 1546 if (cl.isStatic()) {
- 1547 apiWriter.print(" static");
- 1548 }
- 1549 if (cl.isFinal()) {
- 1550 apiWriter.print(" final");
- 1551 }
- 1552 if (cl.isAbstract()) {
- 1553 apiWriter.print(" abstract");
- 1554 }
- 1555 if (cl.isDeprecated()) {
- 1556 apiWriter.print(" deprecated");
- 1557 }
- 1558 apiWriter.print(" ");
- 1559 apiWriter.print(cl.isInterface() ? "interface" : "class");
- 1560 apiWriter.print(" ");
- 1561 apiWriter.print(cl.name());
- 1562 if (cl.hasTypeParameters()) {
- 1563 apiWriter.print(TypeInfo.typeArgumentsName(cl.asTypeInfo().typeArguments(),
- 1564 new HashSet<String>()));
- 1565 }
- 1566
- 1567 if (!cl.isInterface()
- 1568 && !"java.lang.Object".equals(cl.qualifiedName())) {
- 1569 final ClassInfo superclass = cl.filteredSuperclass(filterReference);
- 1570 if (superclass != null && !"java.lang.Object".equals(superclass.qualifiedName())) {
- 1571 apiWriter.print(" extends ");
- 1572 apiWriter.print(superclass.qualifiedName());
- 1573 }
- 1574 }
- 1575
- 1576 List<ClassInfo> interfaces = cl.filteredInterfaces(filterReference).stream()
- 1577 .sorted(ClassInfo.comparator).collect(Collectors.toList());
- 1578 boolean first = true;
- 1579 for (ClassInfo iface : interfaces) {
- 1580 if (first) {
- 1581 apiWriter.print(" implements");
- 1582 first = false;
- 1583 }
- 1584 apiWriter.print(" ");
- 1585 apiWriter.print(iface.qualifiedName());
- 1586 }
- 1587
- 1588 apiWriter.print(" {\n");
- 1589
- 1590 for (MethodInfo mi : constructors) {
- 1591 writeConstructorApi(apiWriter, mi);
- 1592 }
- 1593 for (MethodInfo mi : methods) {
- 1594 writeMethodApi(apiWriter, mi);
- 1595 }
- 1596 for (FieldInfo fi : enums) {
- 1597 writeFieldApi(apiWriter, fi, "enum_constant");
- 1598 }
- 1599 for (FieldInfo fi : fields) {
- 1600 writeFieldApi(apiWriter, fi, "field");
- 1601 }
- 1602
- 1603 apiWriter.print(" }\n\n");
- 1604 return hasWrittenPackageHead;
- 1605 }
- 1606
- 1607 private static void writeClassDexApi(PrintStream apiWriter, ClassInfo cl,
- 1608 Predicate<MemberInfo> filterEmit) {
- 1609 if (filterEmit.test(cl.asMemberInfo())) {
- 1610 apiWriter.print(toSlashFormat(cl.qualifiedName()));
- 1611 apiWriter.print("\n");
- 1612 }
- 1613
- 1614 List<MethodInfo> constructors = cl.getExhaustiveConstructors().stream().filter(filterEmit)
- 1615 .sorted(MethodInfo.comparator).collect(Collectors.toList());
- 1616 List<MethodInfo> methods = cl.getExhaustiveMethods().stream().filter(filterEmit)
- 1617 .sorted(MethodInfo.comparator).collect(Collectors.toList());
- 1618 List<FieldInfo> enums = cl.getExhaustiveEnumConstants().stream().filter(filterEmit)
- 1619 .sorted(FieldInfo.comparator).collect(Collectors.toList());
- 1620 List<FieldInfo> fields = cl.getExhaustiveFields().stream().filter(filterEmit)
- 1621 .sorted(FieldInfo.comparator).collect(Collectors.toList());
- 1622
- 1623 for (MethodInfo mi : constructors) {
- 1624 writeMethodDexApi(apiWriter, cl, mi);
- 1625 }
- 1626 for (MethodInfo mi : methods) {
- 1627 writeMethodDexApi(apiWriter, cl, mi);
- 1628 }
- 1629 for (FieldInfo fi : enums) {
- 1630 writeFieldDexApi(apiWriter, cl, fi);
- 1631 }
- 1632 for (FieldInfo fi : fields) {
- 1633 writeFieldDexApi(apiWriter, cl, fi);
- 1634 }
- 1635 }
- 1636
- 1637 private static void checkSystemPermissions(MethodInfo mi) {
- 1638 boolean hasAnnotation = false;
- 1639 for (AnnotationInstanceInfo a : mi.annotations()) {
- 1640 if (a.type().qualifiedNameMatches("android", "annotation.RequiresPermission")) {
- 1641 hasAnnotation = true;
- 1642 for (AnnotationValueInfo val : a.elementValues()) {
- 1643 ArrayList<AnnotationValueInfo> values = new ArrayList<>();
- 1644 boolean any = false;
- 1645 switch (val.element().name()) {
- 1646 case "value":
- 1647 values.add(val);
- 1648 break;
- 1649 case "allOf":
- 1650 values = (ArrayList<AnnotationValueInfo>) val.value();
- 1651 break;
- 1652 case "anyOf":
- 1653 any = true;
- 1654 values = (ArrayList<AnnotationValueInfo>) val.value();
- 1655 break;
- 1656 }
- 1657 if (values.isEmpty()) continue;
- 1658
- 1659 ArrayList<String> system = new ArrayList<>();
- 1660 ArrayList<String> nonSystem = new ArrayList<>();
- 1661 for (AnnotationValueInfo value : values) {
- 1662 final String perm = String.valueOf(value.value());
- 1663 final String level = Doclava.manifestPermissions.getOrDefault(perm, null);
- 1664 if (level == null) {
- 1665 Errors.error(Errors.REMOVED_FIELD, mi.position(),
- 1666 "Permission '" + perm + "' is not defined by AndroidManifest.xml.");
- 1667 continue;
- 1668 }
- 1669 if (level.contains("normal") || level.contains("dangerous")
- 1670 || level.contains("ephemeral")) {
- 1671 nonSystem.add(perm);
- 1672 } else {
- 1673 system.add(perm);
- 1674 }
- 1675 }
- 1676
- 1677 if (system.isEmpty() && nonSystem.isEmpty()) {
- 1678 hasAnnotation = false;
- 1679 } else if ((any && !nonSystem.isEmpty()) || (!any && system.isEmpty())) {
- 1680 Errors.error(Errors.REQUIRES_PERMISSION, mi, "Method '" + mi.name()
- 1681 + "' must be protected with a system permission; it currently"
- 1682 + " allows non-system callers holding " + nonSystem.toString());
- 1683 }
- 1684 }
- 1685 }
- 1686 }
- 1687 if (!hasAnnotation) {
- 1688 Errors.error(Errors.REQUIRES_PERMISSION, mi, "Method '" + mi.name()
- 1689 + "' must be protected with a system permission.");
- 1690 }
- 1691 }
- 1692
- 1693 private static void checkHiddenTypes(MethodInfo method, Predicate<MemberInfo> filterReference) {
- 1694 checkHiddenTypes(method.returnType(), method, filterReference);
- 1695 List<ParameterInfo> params = method.parameters();
- 1696 if (params != null) {
- 1697 for (ParameterInfo param : params) {
- 1698 checkHiddenTypes(param.type(), method, filterReference);
- 1699 }
- 1700 }
- 1701 }
- 1702
- 1703 private static void checkHiddenTypes(FieldInfo field, Predicate<MemberInfo> filterReference) {
- 1704 checkHiddenTypes(field.type(), field, filterReference);
- 1705 }
- 1706
- 1707 private static void checkHiddenTypes(TypeInfo type, MemberInfo member,
- 1708 Predicate<MemberInfo> filterReference) {
- 1709 if (type == null || type.isPrimitive()) {
- 1710 return;
- 1711 }
- 1712
- 1713 ClassInfo clazz = type.asClassInfo();
- 1714 if (clazz == null || !filterReference.test(clazz.asMemberInfo())) {
- 1715 Errors.error(Errors.HIDDEN_TYPE_PARAMETER, member.position(),
- 1716 "Member " + member + " references hidden type " + type.qualifiedTypeName() + ".");
- 1717 }
- 1718
- 1719 List<TypeInfo> args = type.typeArguments();
- 1720 if (args != null) {
- 1721 for (TypeInfo arg : args) {
- 1722 checkHiddenTypes(arg, member, filterReference);
- 1723 }
- 1724 }
- 1725 }
- 1726
- 1727 static void writeConstructorApi(PrintStream apiWriter, MethodInfo mi) {
- 1728 apiWriter.print(" ctor ");
- 1729 apiWriter.print(mi.scope());
- 1730 if (mi.isDeprecated()) {
- 1731 apiWriter.print(" deprecated");
- 1732 }
- 1733 apiWriter.print(" ");
- 1734 apiWriter.print(mi.name());
- 1735
- 1736 writeParametersApi(apiWriter, mi, mi.parameters());
- 1737 writeThrowsApi(apiWriter, mi.thrownExceptions());
- 1738 apiWriter.print(";\n");
- 1739 }
- 1740
- 1741 static String writeMethodApiWithoutDefault(MethodInfo mi) {
- 1742 final ByteArrayOutputStream out = new ByteArrayOutputStream();
- 1743 writeMethodApi(new PrintStream(out), mi, false);
- 1744 return out.toString();
- 1745 }
- 1746
- 1747 static void writeMethodApi(PrintStream apiWriter, MethodInfo mi) {
- 1748 writeMethodApi(apiWriter, mi, true);
- 1749 }
- 1750
- 1751 static void writeMethodApi(PrintStream apiWriter, MethodInfo mi, boolean withDefault) {
- 1752 apiWriter.print(" method ");
- 1753 apiWriter.print(mi.scope());
- 1754 if (mi.isDefault() && withDefault) {
- 1755 apiWriter.print(" default");
- 1756 }
- 1757 if (mi.isStatic()) {
- 1758 apiWriter.print(" static");
- 1759 }
- 1760 if (mi.isFinal()) {
- 1761 apiWriter.print(" final");
- 1762 }
- 1763 if (mi.isAbstract()) {
- 1764 apiWriter.print(" abstract");
- 1765 }
- 1766 if (mi.isDeprecated()) {
- 1767 apiWriter.print(" deprecated");
- 1768 }
- 1769 if (mi.isSynchronized()) {
- 1770 apiWriter.print(" synchronized");
- 1771 }
- 1772 if (mi.hasTypeParameters()) {
- 1773 apiWriter.print(" " + mi.typeArgumentsName(new HashSet<String>()));
- 1774 }
- 1775 apiWriter.print(" ");
- 1776 if (mi.returnType() == null) {
- 1777 apiWriter.print("void");
- 1778 } else {
- 1779 apiWriter.print(fullParameterTypeName(mi, mi.returnType(), false));
- 1780 }
- 1781 apiWriter.print(" ");
- 1782 apiWriter.print(mi.name());
- 1783
- 1784 writeParametersApi(apiWriter, mi, mi.parameters());
- 1785 writeThrowsApi(apiWriter, mi.thrownExceptions());
- 1786
- 1787 apiWriter.print(";\n");
- 1788 }
- 1789
- 1790 static void writeMethodDexApi(PrintStream apiWriter, ClassInfo cl, MethodInfo mi) {
- 1791 apiWriter.print(toSlashFormat(cl.qualifiedName()));
- 1792 apiWriter.print("->");
- 1793 if (mi.returnType() == null) {
- 1794 apiWriter.print("<init>");
- 1795 } else {
- 1796 apiWriter.print(mi.name());
- 1797 }
- 1798 writeParametersDexApi(apiWriter, mi, mi.parameters());
- 1799 if (mi.returnType() == null) { // constructor
- 1800 apiWriter.print("V");
- 1801 } else {
- 1802 apiWriter.print(toSlashFormat(mi.returnType().dexName()));
- 1803 }
- 1804 apiWriter.print("\n");
- 1805 }
- 1806
- 1807 static void writeParametersApi(PrintStream apiWriter, MethodInfo method,
- 1808 ArrayList<ParameterInfo> params) {
- 1809 apiWriter.print("(");
- 1810
- 1811 for (ParameterInfo pi : params) {
- 1812 if (pi != params.get(0)) {
- 1813 apiWriter.print(", ");
- 1814 }
- 1815 apiWriter.print(fullParameterTypeName(method, pi.type(), pi == params.get(params.size()-1)));
- 1816 // turn on to write the names too
- 1817 if (false) {
- 1818 apiWriter.print(" ");
- 1819 apiWriter.print(pi.name());
- 1820 }
- 1821 }
- 1822
- 1823 apiWriter.print(")");
- 1824 }
- 1825
- 1826 static void writeParametersDexApi(PrintStream apiWriter, MethodInfo method,
- 1827 ArrayList<ParameterInfo> params) {
- 1828 apiWriter.print("(");
- 1829 for (ParameterInfo pi : params) {
- 1830 String typeName = pi.type().dexName();
- 1831 if (method.isVarArgs() && pi == params.get(params.size() - 1)) {
- 1832 typeName += "[]";
- 1833 }
- 1834 apiWriter.print(toSlashFormat(typeName));
- 1835 }
- 1836 apiWriter.print(")");
- 1837 }
- 1838
- 1839 static void writeThrowsApi(PrintStream apiWriter, ArrayList<ClassInfo> exceptions) {
- 1840 // write in a canonical order
- 1841 exceptions = (ArrayList<ClassInfo>) exceptions.clone();
- 1842 Collections.sort(exceptions, ClassInfo.comparator);
- 1843 //final int N = exceptions.length;
- 1844 boolean first = true;
- 1845 for (ClassInfo ex : exceptions) {
- 1846 // Turn this off, b/c we need to regenrate the old xml files.
- 1847 if (true || !"java.lang.RuntimeException".equals(ex.qualifiedName())
- 1848 && !ex.isDerivedFrom("java.lang.RuntimeException")) {
- 1849 if (first) {
- 1850 apiWriter.print(" throws ");
- 1851 first = false;
- 1852 } else {
- 1853 apiWriter.print(", ");
- 1854 }
- 1855 apiWriter.print(ex.qualifiedName());
- 1856 }
- 1857 }
- 1858 }
- 1859
- 1860 static void writeFieldApi(PrintStream apiWriter, FieldInfo fi, String label) {
- 1861 apiWriter.print(" ");
- 1862 apiWriter.print(label);
- 1863 apiWriter.print(" ");
- 1864 apiWriter.print(fi.scope());
- 1865 if (fi.isStatic()) {
- 1866 apiWriter.print(" static");
- 1867 }
- 1868 if (fi.isFinal()) {
- 1869 apiWriter.print(" final");
- 1870 }
- 1871 if (fi.isDeprecated()) {
- 1872 apiWriter.print(" deprecated");
- 1873 }
- 1874 if (fi.isTransient()) {
- 1875 apiWriter.print(" transient");
- 1876 }
- 1877 if (fi.isVolatile()) {
- 1878 apiWriter.print(" volatile");
- 1879 }
- 1880
- 1881 apiWriter.print(" ");
- 1882 apiWriter.print(fi.type().fullName(fi.typeVariables()));
- 1883
- 1884 apiWriter.print(" ");
- 1885 apiWriter.print(fi.name());
- 1886
- 1887 Object val = null;
- 1888 if (fi.isConstant() && fieldIsInitialized(fi)) {
- 1889 apiWriter.print(" = ");
- 1890 apiWriter.print(fi.constantLiteralValue());
- 1891 val = fi.constantValue();
- 1892 }
- 1893
- 1894 apiWriter.print(";");
- 1895
- 1896 if (val != null) {
- 1897 if (val instanceof Integer && "char".equals(fi.type().qualifiedTypeName())) {
- 1898 apiWriter.format(" // 0x%04x '%s'", val,
- 1899 FieldInfo.javaEscapeString("" + ((char)((Integer)val).intValue())));
- 1900 } else if (val instanceof Byte || val instanceof Short || val instanceof Integer) {
- 1901 apiWriter.format(" // 0x%x", val);
- 1902 } else if (val instanceof Long) {
- 1903 apiWriter.format(" // 0x%xL", val);
- 1904 }
- 1905 }
- 1906
- 1907 apiWriter.print("\n");
- 1908 }
- 1909
- 1910 static void writeFieldDexApi(PrintStream apiWriter, ClassInfo cl, FieldInfo fi) {
- 1911 apiWriter.print(toSlashFormat(cl.qualifiedName()));
- 1912 apiWriter.print("->");
- 1913 apiWriter.print(fi.name());
- 1914 apiWriter.print(":");
- 1915 apiWriter.print(toSlashFormat(fi.type().dexName()));
- 1916 apiWriter.print("\n");
- 1917 }
- 1918
- 1919 static void writeKeepList(PrintStream keepListWriter,
- 1920 HashMap<PackageInfo, List<ClassInfo>> allClasses, HashSet<ClassInfo> notStrippable) {
- 1921 // extract the set of packages, sort them by name, and write them out in that order
- 1922 Set<PackageInfo> allClassKeys = allClasses.keySet();
- 1923 PackageInfo[] allPackages = allClassKeys.toArray(new PackageInfo[allClassKeys.size()]);
- 1924 Arrays.sort(allPackages, PackageInfo.comparator);
- 1925
- 1926 for (PackageInfo pack : allPackages) {
- 1927 writePackageKeepList(keepListWriter, pack, allClasses.get(pack), notStrippable);
- 1928 }
- 1929 }
- 1930
- 1931 static void writePackageKeepList(PrintStream keepListWriter, PackageInfo pack,
- 1932 Collection<ClassInfo> classList, HashSet<ClassInfo> notStrippable) {
- 1933 // Work around the bogus "Array" class we invent for
- 1934 // Arrays.copyOf's Class<? extends T[]> newType parameter. (http://b/2715505)
- 1935 if (pack.name().equals(PackageInfo.DEFAULT_PACKAGE)) {
- 1936 return;
- 1937 }
- 1938
- 1939 ClassInfo[] classes = classList.toArray(new ClassInfo[classList.size()]);
- 1940 Arrays.sort(classes, ClassInfo.comparator);
- 1941 for (ClassInfo cl : classes) {
- 1942 writeClassKeepList(keepListWriter, cl, notStrippable);
- 1943 }
- 1944 }
- 1945
- 1946 static void writeClassKeepList(PrintStream keepListWriter, ClassInfo cl,
- 1947 HashSet<ClassInfo> notStrippable) {
- 1948 keepListWriter.print("-keep class ");
- 1949 keepListWriter.print(to$Class(cl.qualifiedName()));
- 1950
- 1951 keepListWriter.print(" {\n");
- 1952
- 1953 ArrayList<MethodInfo> constructors = cl.constructors();
- 1954 Collections.sort(constructors, MethodInfo.comparator);
- 1955 for (MethodInfo mi : constructors) {
- 1956 writeConstructorKeepList(keepListWriter, mi);
- 1957 }
- 1958
- 1959 keepListWriter.print("\n");
- 1960
- 1961 ArrayList<MethodInfo> methods = cl.allSelfMethods();
- 1962 Collections.sort(methods, MethodInfo.comparator);
- 1963 for (MethodInfo mi : methods) {
- 1964 // allSelfMethods is the non-hidden and visible methods. See Doclava.checkLevel.
- 1965 writeMethodKeepList(keepListWriter, mi);
- 1966 }
- 1967
- 1968 keepListWriter.print("\n");
- 1969
- 1970 ArrayList<FieldInfo> enums = cl.enumConstants();
- 1971 Collections.sort(enums, FieldInfo.comparator);
- 1972 for (FieldInfo fi : enums) {
- 1973 writeFieldKeepList(keepListWriter, fi);
- 1974 }
- 1975
- 1976 keepListWriter.print("\n");
- 1977
- 1978 ArrayList<FieldInfo> fields = cl.selfFields();
- 1979 Collections.sort(fields, FieldInfo.comparator);
- 1980 for (FieldInfo fi : fields) {
- 1981 writeFieldKeepList(keepListWriter, fi);
- 1982 }
- 1983
- 1984 keepListWriter.print("}\n\n");
- 1985 }
- 1986
- 1987 static void writeConstructorKeepList(PrintStream keepListWriter, MethodInfo mi) {
- 1988 keepListWriter.print(" ");
- 1989 keepListWriter.print("<init>");
- 1990
- 1991 writeParametersKeepList(keepListWriter, mi, mi.parameters());
- 1992 keepListWriter.print(";\n");
- 1993 }
- 1994
- 1995 static void writeMethodKeepList(PrintStream keepListWriter, MethodInfo mi) {
- 1996 keepListWriter.print(" ");
- 1997 keepListWriter.print(mi.scope());
- 1998 if (mi.isStatic()) {
- 1999 keepListWriter.print(" static");
- 2000 }
- 2001 if (mi.isAbstract()) {
- 2002 keepListWriter.print(" abstract");
- 2003 }
- 2004 if (mi.isSynchronized()) {
- 2005 keepListWriter.print(" synchronized");
- 2006 }
- 2007 keepListWriter.print(" ");
- 2008 if (mi.returnType() == null) {
- 2009 keepListWriter.print("void");
- 2010 } else {
- 2011 keepListWriter.print(getCleanTypeName(mi.returnType()));
- 2012 }
- 2013 keepListWriter.print(" ");
- 2014 keepListWriter.print(mi.name());
- 2015
- 2016 writeParametersKeepList(keepListWriter, mi, mi.parameters());
- 2017
- 2018 keepListWriter.print(";\n");
- 2019 }
- 2020
- 2021 static void writeParametersKeepList(PrintStream keepListWriter, MethodInfo method,
- 2022 ArrayList<ParameterInfo> params) {
- 2023 keepListWriter.print("(");
- 2024
- 2025 for (ParameterInfo pi : params) {
- 2026 if (pi != params.get(0)) {
- 2027 keepListWriter.print(", ");
- 2028 }
- 2029 keepListWriter.print(getCleanTypeName(pi.type()));
- 2030 }
- 2031
- 2032 keepListWriter.print(")");
- 2033 }
- 2034
- 2035 static void writeFieldKeepList(PrintStream keepListWriter, FieldInfo fi) {
- 2036 keepListWriter.print(" ");
- 2037 keepListWriter.print(fi.scope());
- 2038 if (fi.isStatic()) {
- 2039 keepListWriter.print(" static");
- 2040 }
- 2041 if (fi.isTransient()) {
- 2042 keepListWriter.print(" transient");
- 2043 }
- 2044 if (fi.isVolatile()) {
- 2045 keepListWriter.print(" volatile");
- 2046 }
- 2047
- 2048 keepListWriter.print(" ");
- 2049 keepListWriter.print(getCleanTypeName(fi.type()));
- 2050
- 2051 keepListWriter.print(" ");
- 2052 keepListWriter.print(fi.name());
- 2053
- 2054 keepListWriter.print(";\n");
- 2055 }
- 2056
- 2057 static String fullParameterTypeName(MethodInfo method, TypeInfo type, boolean isLast) {
- 2058 String fullTypeName = type.fullName(method.typeVariables());
- 2059 if (isLast && method.isVarArgs()) {
- 2060 // TODO: note that this does not attempt to handle hypothetical
- 2061 // vararg methods whose last parameter is a list of arrays, e.g.
- 2062 // "Object[]...".
- 2063 fullTypeName = type.fullNameNoDimension(method.typeVariables()) + "...";
- 2064 }
- 2065 return fullTypeName;
- 2066 }
- 2067
- 2068 static String to$Class(String name) {
- 2069 int pos = 0;
- 2070 while ((pos = name.indexOf('.', pos)) > 0) {
- 2071 String n = name.substring(0, pos);
- 2072 if (Converter.obtainClass(n) != null) {
- 2073 return n + (name.substring(pos).replace('.', '$'));
- 2074 }
- 2075 pos = pos + 1;
- 2076 }
- 2077 return name;
- 2078 }
- 2079
- 2080 static String toSlashFormat(String name) {
- 2081 String dimension = "";
- 2082 while (name.endsWith("[]")) {
- 2083 dimension += "[";
- 2084 name = name.substring(0, name.length() - 2);
- 2085 }
- 2086
- 2087 final String base;
- 2088 if (name.equals("void")) {
- 2089 base = "V";
- 2090 } else if (name.equals("byte")) {
- 2091 base = "B";
- 2092 } else if (name.equals("boolean")) {
- 2093 base = "Z";
- 2094 } else if (name.equals("char")) {
- 2095 base = "C";
- 2096 } else if (name.equals("short")) {
- 2097 base = "S";
- 2098 } else if (name.equals("int")) {
- 2099 base = "I";
- 2100 } else if (name.equals("long")) {
- 2101 base = "J";
- 2102 } else if (name.equals("float")) {
- 2103 base = "F";
- 2104 } else if (name.equals("double")) {
- 2105 base = "D";
- 2106 } else {
- 2107 base = "L" + to$Class(name).replace(".", "/") + ";";
- 2108 }
- 2109
- 2110 return dimension + base;
- 2111 }
- 2112
- 2113 static String getCleanTypeName(TypeInfo t) {
- 2114 return t.isPrimitive() ? t.simpleTypeName() + t.dimension() :
- 2115 to$Class(t.asClassInfo().qualifiedName() + t.dimension());
- 2116 }
- 2117 }
android系统源码编译报错问题分析处理--持续更新的更多相关文章
- [odroid-pc] ubuntu12.04 64bit Android4.0.3 源码编译报错及解决的方法
第一个错误: host Executable: cmu2nuance (out/host/linux-x86/obj/EXECUTABLES/cmu2nuance_intermedia ...
- 【转】编译Android系统源码和内核源码
原文网址:http://blog.csdn.net/jiangwei0910410003/article/details/37988637 好长时间没有写blog了,之所以没有写,主要还是工作上的事, ...
- FW 编译Android系统源码和内核源码
编译Android系统源码和内核源码 分类: Android2014-07-21 20:58 7287人阅读 评论(28) 收藏 举报 好长时间没有写blog了,之所以没有写,主要还是工作上的事,发现 ...
- 编译Android系统源码和内核源码
[日期:2016-01-11] 来源:Linux社区 作者:jiangwei [字体:大 中 小] 把我之前编译Android系统源码和内核源码的过程记录一下,因为这个过程真的是受益匪浅,看 ...
- 【流媒体开发】VLC Media Player - Android 平台源码编译 与 二次开发详解 (提供详细800M下载好的编译源码及eclipse可调试播放器源码下载)
作者 : 韩曙亮 博客地址 : http://blog.csdn.net/shulianghan/article/details/42707293 转载请注明出处 : http://blog.csd ...
- Android FrameWork 学习之Android 系统源码调试
这是很久以前访问掘金的时候 无意间看到的一个关于Android的文章,作者更细心,分阶段的将学习步骤记录在自己博客中,我觉得很有用,想作为分享同时也是留下自己知识的一些欠缺收藏起来,今后做项目的时候会 ...
- 【安卓本卓】Android系统源码篇之(一)源码获取、源码目录结构及源码阅读工具简介
前言 古人常说,“熟读唐诗三百首,不会作诗也会吟”,说明了大量阅读诗歌名篇对学习作诗有非常大的帮助.做开发也一样,Android源码是全世界最优秀的Android工程师编写的代码,也是A ...
- 如何阅读Android系统源码-收藏必备
对于任何一个对Android开发感兴趣的人而言,对于android系统的学习必不可少.而学习系统最佳的方法就如linus所言:"RTFSC"(Read The Fucking So ...
- 将Android系统源码导入Android studio的方法
Android源码目录结构如下: |-- Makefile|-- abi (applicationbinary interface,应用程序二进制接口,生成libgabi++.so相关库文件)|-- ...
- Android系统源码目录
Android系统源码目录 我们要先了解Android系统源码目录,为后期源码学习打下基础.关于源码的阅读,你可以访问http://androidxref.com/来阅读系统源码.当然,最好是将源码下 ...
随机推荐
- JZOJ 3889
\(\text{Problem}\) 小H是个善于思考的学生,她正在思考一个有关序列的问题. 她的面前浮现出了一个长度为 \(n\) 的序列 \({ai}\),她想找出两个非空的集合 \(S.T\). ...
- 通过Rsync实现文件远程备份
转载:博客园 https://www.cnblogs.com/huligong1234/p/13513395.html
- 钓鱼攻击之:OFFICE 宏后门文件钓鱼
钓鱼攻击之:OFFICE 宏后门文件钓鱼 目录 钓鱼攻击之:OFFICE 宏后门文件钓鱼 1 宏病毒介绍 1.1 Word 宏 1.2 Excel 4.0宏 2 生成 Word 宏后门 3 利用DOC ...
- PostgreSQL cache lookup failed for type XXXX 错误
一.错误信息 执行 pg_dump 命令备份,提示 cache lookup failed for type- 错误. 二.错误分析 根据上面日志中的提示信息,可以确定 222222 这个 ID 号, ...
- torch.nn.Embedding使用详解
torch.nn.Embedding: 随机初始化词向量,词向量值在正态分布N(0,1)中随机取值.输入:torch.nn.Embedding(num_embeddings, – 词典的大小尺寸,比如 ...
- (五) Mysql 之锁详细篇
一.锁的分类1.范围:全局锁.表级锁.行级锁2.功能分类:共享锁.排它锁 二.数据库的全局锁 加锁:mysql> flush tables with read lock; 释放锁:mysql&g ...
- vue模板三目运算判断报错
问题: 关于vue三目运算符提示报错 1.三目运算符等于判断 {{ a==b ? '是' : '否'}} 2.其他三目运算符 <代表小于号(<) >代表大于符号(>) ≤表示小 ...
- linux 操作命令大全
mysql 授权远程访问 1.进入cd /usr/local/mysql/bin 下执行 ./mysql -uroot -pInfosec@2020 (-p后面是数据库密码) 2.use mysql ...
- 两步解决php超时问题
tp的报错很模糊,需要自己判断是不是超时问题 首先给Apache的配置文件httpd.conf添加几行: <IfModule mod_fcgid.c> FcgidProcessLifeTi ...
- 查电脑并修改IP地址,你晓得吗?
查电脑并修改IP地址,你晓得吗? 好记性不如烂笔头,古人的话,浅显却好有深意,越品越有味道. 每次都会忘记怎么查电脑IP,那么今天就写下来吧! 方法一:通过命令行查询IP地址 快捷键Win ...