相关文章推荐
满身肌肉的炒饭  ·  服务商和渠道商的区别 | 微信开放社区·  8 月前    · 
慷慨的蚂蚁  ·  从星期一而不是星期天开始antd ...·  1 年前    · 
无邪的消炎药  ·  PyQt5滑块控制灰度图的二值化范围_qt ...·  1 年前    · 
重情义的蟠桃  ·  file.delete()返回true,但是 ...·  1 年前    · 
忐忑的显示器  ·  django模型的crud操作 - ...·  1 年前    · 
Code  ›  Android构建流程——篇二_小宝一号的博客
android开发 input gradle aidl
https://blog.csdn.net/dbs1215/article/details/106889432
爱玩的牙膏
2 年前
    • 预操作
    • 任务列表
    • 如何查看一个task类
    • Task1: checkDebugClasspath
      • 1. input/output
      • 2. 如何找到任务实现类
      • 3. 核心类(AppClasspathCheckTask)
    • Task2: preDebugBuild
      • 1. input/ouput
      • 2. 核心类(AppPreBuildTask)
    • Task3: compileDebugAidl
      • 1. input/output
      • 2. 核心类(AidlCompile)
      • 3. 映射文件
    • Task4: compileDebugRenderscript
      • 1. RenderScript 概览
      • 2. input/ouput
      • 3. 核心类(RenderscriptCompile)

      为说明Android构建过程中gradle执行的各task,写了简单demo

      git clone https://github.com/xiaobaoyihao/AndroidGradleTaskDemo.git
      

      先罗列下Android构建流程中任务有哪些,本系列讲解都是基于gradle plugin 3.2.0源码

      clone下demo,终端执行

      ./gradlew assembleDebug --console=plain
      

      输出如下任务链

      :app:checkDebugClasspath UP-TO-DATE
      :app:preBuild UP-TO-DATE
      :app:preDebugBuild UP-TO-DATE
      :app:compileDebugAidl UP-TO-DATE
      :app:compileDebugRenderscript UP-TO-DATE
      :app:checkDebugManifest UP-TO-DATE
      :app:generateDebugBuildConfig UP-TO-DATE
      :app:prepareLintJar UP-TO-DATE
      :app:mainApkListPersistenceDebug UP-TO-DATE
      :app:generateDebugResValues UP-TO-DATE
      :app:generateDebugResources UP-TO-DATE
      :app:mergeDebugResources UP-TO-DATE
      :app:createDebugCompatibleScreenManifests UP-TO-DATE
      :app:processDebugManifest UP-TO-DATE
      :app:splitsDiscoveryTaskDebug UP-TO-DATE
      :app:processDebugResources UP-TO-DATE
      :app:generateDebugSources UP-TO-DATE
      :app:javaPreCompileDebug UP-TO-DATE
      :app:compileDebugJavaWithJavac UP-TO-DATE
      :app:compileDebugNdk NO-SOURCE
      :app:compileDebugSources UP-TO-DATE
      :app:mergeDebugShaders UP-TO-DATE
      :app:compileDebugShaders UP-TO-DATE
      :app:generateDebugAssets UP-TO-DATE
      :app:mergeDebugAssets UP-TO-DATE
      :app:transformClassesWithDexBuilderForDebug UP-TO-DATE
      :app:transformDexArchiveWithExternalLibsDexMergerForDebug UP-TO-DATE
      :app:transformDexArchiveWithDexMergerForDebug UP-TO-DATE
      :app:mergeDebugJniLibFolders UP-TO-DATE
      :app:transformNativeLibsWithMergeJniLibsForDebug UP-TO-DATE
      :app:checkDebugLibraries UP-TO-DATE
      :app:processDebugJavaRes NO-SOURCE
      :app:transformResourcesWithMergeJavaResForDebug UP-TO-DATE
      :app:validateSigningDebug UP-TO-DATE
      :app:packageDebug UP-TO-DATE
      :app:assembleDebug UP-TO-DATE
      

      为了更清楚观察各任务,我们可以对每个任务的输入和输出添加日志打印,在demo中放开build.gradle中任务打印区域代码

      如何查看一个task类

      可以通过taskname来查找,一般任务路径大部分都是在

      com.android.build.gradle.internal.tasks
      com.android.build.gradle.tasks
      

      目录下,任务名称基本和类名一致

      Task1: checkDebugClasspath

      1. input/output

      input:/Users/apple/.gradle/caches/transforms-1/files-1.1/appcompat-v7-26.1.0.aar/2774ea4f1cf1e83a6ad8e8d3c8b463b6/jars/classes.jar
      input:/Users/apple/.gradle/caches/transforms-1/files-1.1/constraint-layout-1.1.3.aar/f43c0ba95b6494825ed940fc4f04662b/jars/classes.jar
      input:/Users/apple/.gradle/caches/transforms-1/files-1.1/animated-vector-drawable-26.1.0.aar/559112320064089dfaf6780e71d5b44f/jars/classes.jar
      input:/Users/apple/.gradle/caches/transforms-1/files-1.1/support-vector-drawable-26.1.0.aar/c2c3ad4abfd49316f6769b8238b0f010/jars/classes.jar
      input:/Users/apple/.gradle/caches/transforms-1/files-1.1/support-v4-26.1.0.aar/9ac5f97e8ccb24c52b7cbb6202c12ad0/jars/classes.jar
      input:/Users/apple/.gradle/caches/transforms-1/files-1.1/support-media-compat-26.1.0.aar/53ab5ad72634f3497309a8788f3ca200/jars/classes.jar
      input:/Users/apple/.gradle/caches/transforms-1/files-1.1/support-fragment-26.1.0.aar/7e6a4ce6591d722d47aafc36d980f8b4/jars/classes.jar
      input:/Users/apple/.gradle/caches/transforms-1/files-1.1/support-core-utils-26.1.0.aar/4c474caa9ac1f01c4936bd96905ecacd/jars/classes.jar
      input:/Users/apple/.gradle/caches/transforms-1/files-1.1/support-core-ui-26.1.0.aar/868eaa7e0c620cd85d72ad4f340e8bb1/jars/classes.jar
      input:/Users/apple/.gradle/caches/transforms-1/files-1.1/support-compat-26.1.0.aar/4ec3c1c46e5bad9ac3b91f45a2afec3e/jars/classes.jar
      input:/Users/apple/.gradle/caches/modules-2/files-2.1/com.android.support/support-annotations/26.1.0/814258103cf26a15fcc26ecce35f5b7d24b73f8/support-annotations-26.1.0.jar
      input:/Users/apple/.gradle/caches/modules-2/files-2.1/com.android.support.constraint/constraint-layout-solver/1.1.3/bde0667d7414c16ed62d3cfe993cff7f9d732373/constraint-layout-solver-1.1.3.jar
      input:/Users/apple/.gradle/caches/transforms-1/files-1.1/runtime-1.0.0.aar/5b2333922ba05b1f174de51739b24d14/jars/classes.jar
      input:/Users/apple/.gradle/caches/modules-2/files-2.1/android.arch.lifecycle/common/1.0.0/e414a4cb28434e25c4f6aa71426eb20cf4874ae9/common-1.0.0.jar
      input:/Users/apple/.
      
      
      
      
          
      gradle/caches/modules-2/files-2.1/android.arch.core/common/1.0.0/a2d487452376193fc8c103dd2b9bd5f2b1b44563/common-1.0.0.jar
      =========================================================
      output:/Users/apple/work/project/AndroidGradleTaskDemo/app/build/intermediates/checkDebugClasspath/debug
      

      从task字面可以猜测出该任务是对app classpath做校验,具体是在那个类呢?
      我们找到到AppClasspathCheckTask.java,如何确定是正确的呢?
      我们发现该类中有个ConfigAction.getName方法

      在这里插入图片描述
      其实这个方法的返回字符串就是执行的任务名(checkDebugClasspath),具体怎么流程大家直接看代码就知道了

      ConfigAction被调用的地方

      核心入口代码

      //ApplicationTaskManager.java
      @Override
        protected Task createVariantPreBuildTask(@NonNull VariantScope scope) {
            final VariantType variantType = scope.getVariantConfiguration().getType();
            if (variantType.isApk()) {
                AppClasspathCheckTask classpathCheck =
                        taskFactory.create(new AppClasspathCheckTask.ConfigAction(scope));
                return (variantType.isTestComponent()
                                ? taskFactory.create(new TestPreBuildTask.ConfigAction(scope))
                                : taskFactory.create(new AppPreBuildTask.ConfigAction(scope)))
                        .dependsOn(classpathCheck);
            return super.createVariantPreBuildTask(scope);
      

      有人会问中间的debug怎么多出来?追踪getName方法内部实现发现最终调用BaseVariantData.getTaskName方法

      public String getTaskName(@NonNull String prefix, @NonNull String suffix) {
          return StringHelper.appendCapitalized(prefix, variantConfiguration.getFullName(), suffix);
      // VariantConfiguration.java
       public String getFullName() {
           if (mFullName == null) {
               mFullName =
                       computeFullName(
                               getFlavorName(),
                               mBuildType,
                               mType,
                               mTestedConfig == null ? null : mTestedConfig.getType());
           return mFullName;
           * Returns the full, unique name of the variant in camel case (starting with a lower case),
           * including BuildType, Flavors and Test (if applicable).
           * @param flavorName the flavor name, as computed by {@link #computeFlavorName(List)}
           * @param buildType the build type
           * @param type the variant type
           * @return the name of the variant
       public static <B extends BuildType> String computeFullName(
                  @NonNull String flavorName,
                  @NonNull B buildType,
                  @NonNull VariantType type,
                  @Nullable VariantType testedType) {
           StringBuilder sb = new StringBuilder();
           if (!flavorName.isEmpty()) {
               sb.append(flavorName);
               StringHelper.appendCapitalized(sb, buildType.getName());
           } else {
               sb.append(buildType.getName());
           if (type.isHybrid()) {
               sb.append("Feature");
           if (type.isTestComponent()) {
               if (testedType != null && testedType.isHybrid()) {
                   sb.append("Feature");
               sb.append(type.getSuffix());
           return sb.toString();
      

      可以看到computeFullName是返回variant相关的名字,和我们输入的assembleDebug相匹配,所以我们后期直接通过任务名就能准确找到对应ConfigAction类了这样真正的Task类名也就找到了

      2. 如何找到任务实现类

      确定任务名 -> 在所有TaskConfigAction的子类中寻找getName返回值是否与其task名匹配 -> 对应Task实现类

      3. 核心类(AppClasspathCheckTask)

      //AppClasspathCheckTask.java
      @TaskAction
      void run() {
           compareClasspaths();
      //ClasspathComparisionTask.java
      void compareClasspaths() {
      	//com.android.support:appcompat-v7:23.3.0
      	//group:module/artifact:version
           Set<ResolvedArtifactResult> runtimeArtifacts = runtimeClasspath.getArtifacts();
           Set<ResolvedArtifactResult> compileArtifacts = compileClasspath.getArtifacts();
           // Store a map of groupId -> (artifactId -> versions)
           Map<String, Map<String, String>> runtimeIds =
                   Maps.newHashMapWithExpectedSize(runtimeArtifacts.size());
      	//1. 存储runtime依赖版本信息到map中groupId -> (artifactId -> versions)
           for (ResolvedArtifactResult artifact : runtimeArtifacts) {
               // only care about external dependencies to compare versions.
               final ComponentIdentifier componentIdentifier =
                       artifact.getId(
      
      
      
      
          
      ).getComponentIdentifier();
               if (componentIdentifier instanceof ModuleComponentIdentifier) {
                   ModuleComponentIdentifier moduleId =
                           (ModuleComponentIdentifier) componentIdentifier;
                   // get the sub-map, creating it if needed.
                   Map<String, String> subMap =
                           runtimeIds.computeIfAbsent(moduleId.getGroup(), s -> new HashMap<>());
                   subMap.put(moduleId.getModule(), moduleId.getVersion());
      	//对compileArtifacts集合进行遍历,并和compileArtifacts中相同的group.module比较,如何发现版本不一致,调用onDifferentVersionsFound方法
           for (ResolvedArtifactResult artifact : compileArtifacts) {
               // only care about external dependencies to compare versions.
               final ComponentIdentifier componentIdentifier =
                       artifact.getId().getComponentIdentifier();
               if (componentIdentifier instanceof ModuleComponentIdentifier) {
                   ModuleComponentIdentifier moduleId =
                           (ModuleComponentIdentifier) componentIdentifier;
                   Map<String, String> subMap = runtimeIds.get(moduleId.getGroup());
                   if (subMap == null) {
                       continue;
                   String runtimeVersion = subMap.get(moduleId.getModule());
                   if (runtimeVersion == null) {
                       continue;
                   if (runtimeVersion.equals(moduleId.getVersion())) {
                       continue;
                   onDifferentVersionsFound(
                           moduleId.getGroup(),
                           moduleId.getModule(),
                           runtimeVersion,
                           moduleId.getVersion());
      //AppClasspathCheckTask.java
      @Override
      void onDifferentVersionsFound(
               @NonNull String group,
               @NonNull String module,
               @NonNull String runtimeVersion,
               @NonNull String compileVersion) {
      	//这个方法很简单,就是比较版本不一样的话,会提示依赖有冲突,运行时可能导致crash
           String suggestedVersion;
           try {
               GradleVersion runtime = GradleVersion.parse(runtimeVersion);
               GradleVersion compile = GradleVersion.parse(compileVersion);
               if (runtime.compareTo(compile) > 0) {
                   suggestedVersion = runtimeVersion;
               } else {
                   suggestedVersion = compileVersion;
           } catch (Throwable e) {
               // in case we are unable to parse versions for some reason, choose runtime
               suggestedVersion = runtimeVersion;
           String message =
                   String.format(
                           "Conflict with dependency '%1$s:%2$s' in project '%3$s'. Resolved versions for "
                                   + "runtime classpath (%4$s) and compile classpath (%5$s) differ. This "
                                   + "can lead to runtime crashes. To resolve this issue follow "
                                   + "advice at https://developer.android.com/studio/build/gradle-tips#configure-project-wide-properties. "
                                   + "Alternatively, you can try to fix the problem "
                                   + "by adding this snippet to %6$s:\n"
                                   + "dependencies {\n"
                                   + "    implementation(\"%1$s:%2$s:%7$s\")\n"
                                   + "}\n",
                           group,
                           module,
                           getProject().getPath(),
                           runtimeVersion,
                           compileVersion,
                           getProject().getBuildFile(),
                           suggestedVersion);
           reporter.reportWarning(EvalIssueReporter.Type.GENERIC, message);
      

      简单总结:

      该任务就是对编译类路径和运行时类路径进行校验,如果相同的group.module中存在不同version,则提示用户依赖有冲突,会导致运行是crash

      冲突解决方案参见官网

      Task2: preDebugBuild

      1. input/ouput

      taskName:preDebugBuild
      input:/Users/apple/.gradle/caches/transforms-1/files-1.1/appcompat-v7-26.1.0.aar/2774ea4f1cf1e83a6ad8e8d3c8b463b6/AndroidManifest.xml
      input:/Users/apple/.gradle/caches/transforms-1/files-1.1/constraint-layout-1.1.3.aar/f43c0ba95b6494825ed940fc4f04662b/AndroidManifest.xml
      input:/Users/apple/.gradle/caches/transforms-1/files-1.1/animated-vector-drawable-26.1.0.aar/559112320064089dfaf6780e71d5b44f/AndroidManifest.xml
      input:/Users/apple/.gradle/caches/transforms-1/files-1.1/support-vector-drawable-26.1.0.aar/c2c3ad4abfd49316f6769b8238b0f010/AndroidManifest.xml
      input:/Users/apple/.gradle/caches/transforms-1/files-1.1/support-v4-26.1.0.aar/9ac5f97e8ccb24c52b7cbb6202c12ad0/AndroidManifest.xml
      input:/Users/apple/.gradle/caches/transforms-1/files-1.1/support-media-compat-26.1.0.aar/53ab5ad72634f3497309a8788f3ca200/AndroidManifest.xml
      input:/Users/apple/.gradle/caches/transforms-1/files-1.1/support-fragment-26.1.0.aar/7e6a4ce6591d722d47aafc36d980f8b4/AndroidManifest.xml
      input:/Users/apple/.gradle/caches/transforms-1/files-1.1/support-core-utils-26.1.0.aar/4c474caa9ac1f01c4936bd96905ecacd/AndroidManifest.xml
      input:/Users/apple/.gradle/caches/transforms-1/files-1.1/support-core-ui-26.1.0.aar/868eaa7e0c620cd85d72ad4f340e8bb1/AndroidManifest.xml
      input:/Users/apple/.gradle/caches/transforms-1/files-1.1/support-compat-26.1.0.aar/4ec3c1c46e5bad9ac3b91f45a2afec3e/AndroidManifest.xml
      input:/Users/apple/.gradle/caches/transforms-1/files-1.1/runtime-1.0.0.aar/5b2333922ba05b1f174de51739b24d14/AndroidManifest.xml
      =========================================================
      output:/Users/apple/work/project/AndroidGradleTaskDemo/app/build/intermediates/prebuild/debug
      

      输入都为依赖库的清单文件,输出为空;这个任务简单说也是对应用变体做校验

      2. 核心类(AppPreBuildTask)

      @TaskAction
      void run() {
          Set<ResolvedArtifactResult> compileArtifacts = new HashSet<>();
          compileArtifacts.addAll(compileManifests.getArtifacts());
          compileArtifacts.addAll(compileNonNamespacedManifests.getArtifacts());
          Set<ResolvedArtifactResult>
      
      
      
      
          
       runtimeArtifacts = new HashSet<>();
          runtimeArtifacts.addAll(runtimeManifests.getArtifacts());
          runtimeArtifacts.addAll(runtimeNonNamespacedManifests.getArtifacts());
          // create a map where the key is either the sub-project path, or groupId:artifactId for
          // external dependencies.
          // For external libraries, the value is the version.
          Map<String, String> runtimeIds = Maps.newHashMapWithExpectedSize(runtimeArtifacts.size());
          // build a list of the runtime artifacts
          for (ResolvedArtifactResult artifact : runtimeArtifacts) {
              handleArtifact(artifact.getId().getComponentIdentifier(), runtimeIds::put);
          // run through the compile ones to check for provided only.
          for (ResolvedArtifactResult artifact : compileArtifacts) {
              final ComponentIdentifier compileId = artifact.getId().getComponentIdentifier();
              handleArtifact(
                      compileId,
                      (key, value) -> {
                      	//校验代码逻辑
                          String runtimeVersion = runtimeIds.get(key);
                          if (runtimeVersion == null) {
                              if (isBaseModule) {
                                  String display = compileId.getDisplayName();
                                  throw new RuntimeException(
                                          "Android dependency '"
                                                  + display
                                                  + "' is set to compileOnly/provided which is not supported");
                          } else if (!runtimeVersion.isEmpty()) {
                              // compare versions.
                              if (!runtimeVersion.equals(value)) {
                                  throw new RuntimeException(
                                          String.format(
                                                  "Android dependency '%s' has different version for the compile (%s) and runtime (%s) classpath. You should manually set the same version via DependencyResolution",
                                                  key, value, runtimeVersion));
                      });
      private void handleArtifact(
                  @NonNull ComponentIdentifier id, @NonNull BiConsumer<String, String> consumer) {
          if (id instanceof ProjectComponentIdentifier) {
               consumer.accept(((ProjectComponentIdentifier) id).getProjectPath().intern(), "");
           } else if (id instanceof ModuleComponentIdentifier) {
               ModuleComponentIdentifier moduleComponentId = (ModuleComponentIdentifier) id;
               consumer.accept(
                       moduleComponentId.getGroup() + ":" + moduleComponentId.getModule(),
                       moduleComponentId.getVersion());
           } else if (id instanceof OpaqueComponentArtifactIdentifier) {
               // skip those for now.
               // These are file-based dependencies and it's unlikely to be an AAR.
           } else {
               getLogger()
                       .warn(
                               "Unknown ComponentIdentifier type: "
                                       + id.getClass().getCanonicalName());
      

      如果用compileOnly、provider修饰aar则会失败

      验证下我们的想法,add 如下代码到app.build.gradle中

      compileOnly 'com.facebook.stetho:stetho:1.5.0'
      
      ./gradlew preDebugBuild
      

      执行结果
      在这里插入图片描述
      可以反推compileOnly不支持修饰aar只支持jar
      补充下AppClasspathCheckTask是AppPreBuildTask任务前置条件,在👇的图可以体现出来

      Task3: compileDebugAidl

      1. input/output

      taskName:compileDebugAidl
      input:/Users/apple/.gradle/caches/transforms-1/files-1.1/support-media-compat-26.1.0.aar/53ab5ad72634f3497309a8788f3ca200/aidl
      input:/Users/apple/.gradle/caches/transforms-1/files-1.1/support-compat-26.1.0.aar/4ec3c1c46e5bad9ac3b91f45a2afec3e/aidl
      input:/Users/apple/work/project/AndroidGradleTaskDemo/app/src/main/aidl/com/gradle/task/demo/IHelloAidlInterface.aidl
      =========================================================
      output:/Users/apple/work/project/AndroidGradleTaskDemo/app/build/intermediates/incremental/compileDebugAidl
      output:/Users/apple/work/project/AndroidGradleTaskDemo/app/build/generated/source/aidl/debug
      
      1. 可以看出该任务是扫描工程下依赖的所有aidl文件,并生成对应的java文件
      2. 在生成dependency.store文件
        在这里插入图片描述 在这里插入图片描述
      inputoutput备注
      *.aidlbuild/*.javajava源文件
      -dependency.store.aidl -> .java映射文件表

      2. 核心类(AidlCompile)

      先来看下该类继承关系
      AidlCompile -> IncrementalTask(abstract)

      //IncrementalTask.java
       * Gradle's entry-point into this task. Determines whether or not it's possible to do this task
       * incrementally and calls either doIncrementalTaskAction() if an incremental build is possible,
       * and doFullTaskAction() if not.
      @TaskAction
      void taskAction(IncrementalTaskInputs inputs) throws Exception {
      	//如果是非增量操作,直接走全量操作方法
          if (!isIncremental() || !inputs.isIncremental()) {
              getProject().getLogger().info("Unable do incremental execution: full task run");
      		//交给子类实现
              doFullTaskAction
      
      
      
      
          
      ();
              return;
      	//走增量操作方法,并携带变更的输入文件,交给子类实现
          doIncrementalTaskAction(getChangedInputs(inputs));
      private Map<File, FileStatus> getChangedInputs(IncrementalTaskInputs inputs) {
         final Map<File, FileStatus> changedInputs = Maps.newHashMap();
          inputs.outOfDate(
                  change -> {
                      FileStatus status = change.isAdded() ? FileStatus.NEW : FileStatus.CHANGED;
                      changedInputs.put(change.getFile(), status);
                  });
          inputs.removed(change -> changedInputs.put(change.getFile(), FileStatus.REMOVED));
          return changedInputs;
      

      可以看到该任务主流程逻辑还是比较简单,如果是全量动作,走doFullTaskAction方法,否则走doIncrementalTaskAction增量操作,我们先来看下全量操作

      doFullTaskAction

      /** Task to compile aidl files. Supports incremental update. */
      @CacheableTask
      public class AidlCompile extends IncrementalTask {
      	private static final String DEPENDENCY_STORE = "dependency.store";
          private static final PatternSet PATTERN_SET = new PatternSet().include("**/*.aidl");
      	@Override
      	protected void doFullTaskAction() throws IOException {
      		//1. 全量操作前,先对输出目录做下清理操作
      	    // this is full run, clean the previous output
      	    File destinationDir = getSourceOutputDir();
      	    File parcelableDir = getPackagedDir();
      	    FileUtils.cleanOutputDir(destinationDir);
      	    if (parcelableDir != null) {
      	        FileUtils.cleanOutputDir(parcelableDir);
      		//2. 编译所有aidl文件
      	    DepFileProcessor processor = new DepFileProcessor();
      	    try {
      	        compileAllFiles(processor);
      	    } catch (Exception e) {
      	        throw new RuntimeException(e);
      		//3. 生成aid->java映射文件
      	    List<DependencyData> dataList = processor.getDependencyDataList();
      	    DependencyDataStore store = new DependencyDataStore();
      	    store.addData(dataList);
      	    try {
      	        store.saveTo(new File(getIncrementalFolder(), DEPENDENCY_STORE));
      	    } catch (IOException e) {
      	        throw new RuntimeException(e);
      	@InputFiles
      	@SkipWhenEmpty
      	@PathSensitive(PathSensitivity.RELATIVE)
      	public FileTree getSourceFiles() {
      	    // this is because aidl may be in the same folder as Java and we want to restrict to
      	    // .aidl files and not java files.
      	    return getProject().files(sourceDirs.get()).getAsFileTree().matching(PATTERN_SET);
      @InputFiles
      @SkipWhenEmpty
      @PathSensitive(PathSensitivity.RELATIVE)
      public FileTree getSourceFiles() {
          // this is because aidl may be in the same folder as Java and we want to restrict to
          // .aidl files and not java files.
          return getProject().files(sourceDirs.get()).getAsFileTree().matching(PATTERN_SET);
      

      可以看到关键方法是compileAllFiles它是调用aidl工具生成了java源文件,进去看下

      public void compileAllAidlFiles(
                  @NonNull Collection<File> sourceFolders,
                  @NonNull File sourceOutputDir,
                  @Nullable File packagedOutputDir,
                  @Nullable Collection<String> packageWhiteList,
                  @NonNull Collection<File> importFolders,
                  @Nullable DependencyFileProcessor dependencyFileProcessor,
                  @NonNull ProcessOutputHandler processOutputHandler)
                  throws IOException, InterruptedException, ProcessException {
          //1. 校验输入参数
          checkNotNull(sourceFolders, "sourceFolders cannot be null.");
          checkNotNull(sourceOutputDir, "sourceOutputDir cannot be null.");
          checkNotNull(importFolders, "importFolders cannot be null.");
          checkState(mTargetInfo != null,
                  "Cannot call compileAllAidlFiles() before setTargetInfo() is called.");
          IAndroidTarget target = mTargetInfo.getTarget();
          BuildToolInfo buildToolInfo = mTargetInfo.getBuildTools();
      	//2. 关键点,获取aidl工具路径(先确定buildTool版本,在从buildTool工具包中找aidl工具包,见下图);便于以后调用
          String aidl = buildToolInfo.getPath(BuildToolInfo.PathId.AIDL);
          if (aidl ==
      
      
      
      
          
       null || !new File(aidl).isFile()) {
              throw new IllegalStateException("aidl is missing from '" + aidl + "'");
          List<File> fullImportList = Lists.newArrayListWithCapacity(
                  sourceFolders.size() + importFolders.size());
          fullImportList.addAll(sourceFolders);
          fullImportList.addAll(importFolders);
      	//3. 构建一个aidl处理器,用来生成java文件
          AidlProcessor processor = new AidlProcessor(
                  aidl,
                  target.getPath(IAndroidTarget.ANDROID_AIDL),
                  fullImportList,
                  sourceOutputDir,
                  packagedOutputDir,
                  packageWhiteList,
                  dependencyFileProcessor != null ?
                          dependencyFileProcessor : DependencyFileProcessor.NO_OP,
                  mProcessExecutor,
                  processOutputHandler);
      	//4. 对输入的aidl文件集合进行遍历,一次执行编译操作
          for (File dir : sourceFolders) {
              DirectoryWalker.builder()
                      .root(dir.toPath())
                      .extensions("aidl")
                      .action(processor)
                      .build()
                      .walk();
      
      DirectoryWalker.walk -> AidlProcessor.call -> GradleProcessExecutor.execute
      

      贴下AidlProcessor.call部分代码

      public void call(@NonNull Path startDir, @NonNull Path path) throws IOException {
         ProcessInfoBuilder builder = new ProcessInfoBuilder();
          builder.setExecutable(mAidlExecutable);
          builder.addArgs("-p" + mFrameworkLocation);
          builder.addArgs("-o" + mSourceOutputDir.getAbsolutePath());
          // add all the library aidl folders to access parcelables that are in libraries
          for (File f : mImportFolders) {
              builder.addArgs("-I" + f.getAbsolutePath());
          // create a temp file for the dependency
          File depFile = File.createTempFile("aidl", ".d");
          builder.addArgs("-d" + depFile.getAbsolutePath());
          builder.addArgs(path.toAbsolutePath().toString());
          ProcessResult result = mProcessExecutor.execute(
                  builder.createProcess(), mProcessOutputHandler);
          ...
      

      3. 映射文件

      简单梳理下,第三部就是生成dependency.store文件了,这个就过了,大家有兴趣自己看好啦。
      增量操作这里简单说下主要分几步操作

      1. 读取dependency.store文件,如果读取失败,直接走全量操作,并删除dependency.store文件
      2. 对changedInputs文件进行遍历判断
        1. 文件新增 -> 直接进行编译处理
        2. 文件是删除 -> 直接进行清理操作
        3. 文件修改 -> 读取文件依赖的所有选项,并对其进行编译处理

      依赖任务:preBuildTask

      public AidlCompile createAidlTask(@NonNull VariantScope scope) {
         AidlCompile aidlCompileTask = taskFactory.create(new AidlCompile.ConfigAction(scope));
          scope.getTaskContainer().setAidlCompileTask(aidlCompileTask);
          scope.getTaskContainer().getSourceGenTask().dependsOn(aidlCompileTask);
      	//依赖preBuildTask
          aidlCompileTask.dependsOn(scope.getTaskContainer().getPreBuildTask());
          return aidlCompileTask;
      

      Task4: compileDebugRenderscript

      1. RenderScript 概览

      RenderScript 是用于在 Android 上以高性能运行计算密集型任务的框架。RenderScript 主要用于数据并行计算,不过串行工作负载也可以从中受益。RenderScript 运行时可在设备上提供的多个处理器(如多核 CPU 和 GPU)间并行调度工作。这样您就能够专注于表达算法而不是调度工作。RenderScript 对于执行图像处理、计算摄影或计算机视觉的应用来说尤其有用。

      2. input/ouput

      taskName:compileDebugRenderscript
      input:/Users/apple/work/project/AndroidGradleTaskDemo/app/src/debug/rs
      input:/Users/apple/work/project/AndroidGradleTaskDemo/app/src/main/rs
      =========================================================
      output:/Users/apple/work/project/AndroidGradleTaskDemo/app/build/intermediates/rs/debug/lib
      output:/Users/apple/work/project/AndroidGradleTaskDemo/app/build/intermediates/rs/debug/obj
      output:/Users/apple/work/project/AndroidGradleTaskDemo/app/build/generated/res/rs/debug
      output:/Users/apple/work/project/AndroidGradleTaskDemo/app/build/generated/source/rs/debug
      

      3. 核心类(RenderscriptCompile)

      套路和任务3差不多,调用工具(llvm-rs-cc)生成源文件

      @TaskAction
      void taskAction() throws IOException, InterruptedException, ProcessException {
      	 // 1.预操作,清理作用
           // this is full run (always), clean the previous outputs
           File sourceDestDir = getSourceOutputDir();
           FileUtils.cleanOutputDir(sourceDestDir);
           File resDestDir = getResOutputDir();
           FileUtils.cleanOutputDir(resDestDir);
           File objDestDir = getObjOutputDir();
           FileUtils.cleanOutputDir(objDestDir);
           File libDestDir = getLibOutputDir();
           FileUtils.cleanOutputDir(libDestDir);
           Set<File> sourceDirectories = sourceDirs.getFiles();
      	 //2. 编译所有rs文件,套路和aidl差不多
           getBuilder()
                   .compileAllRenderscriptFiles(
                           sourceDirectories,
                           getImportFolders(),
                           sourceDestDir,
                           resDestDir,
                           objDestDir,
                           libDestDir,
                           getTargetApi(),
                           isDebugBuild(),
                           getOptimLevel(),
                           isNdkMode(),
                           isSupportMode(),
                           useAndroidX(),
                           getNdkConfig() == null ? null : getNdkConfig().getAbiFilters(),
                           new LoggedProcessOutputHandler(getILogger()));
      

      编译关键代码
      在这里插入图片描述

      具体细节不再阐述了,大家有兴趣自己看源码

      👇
      Android构建流程——上篇
      Android构建流程——下篇

      https://developer.android.com/studio/build/dependencies#resolution_errors

      compileOnly的限制

      Android新配置说明

      https://developer.android.com/guide/topics/renderscript/compute?hl=zh-cn

      Android构建流程——篇二预操作任务列表预操作为说明Android构建过程中gradle执行的各task,写了简单demogit clone https://github.com/xiaobaoyihao/AndroidGradleTaskDemo.git任务列表 17.6.1 案例运行效果 488 17.6.2 加载物体类——loadedobjectvertexnormal 488 17.6.3 加载物体刚体类——loadrigidbody 490 17.7 铰链关节 491 17.7.1 铰链关节的基本知识 491 17.7.2 案例的运行效果 492 17.7.3 铰链关节旋转角速度的计算 493 17.7.4 3d界面渲染类——mysurfaceview 494 17.8 滑动关节 496 17.8.1 滑动关节的基本知识 496 17.8.2 案例效果图 497 17.8.3 3d界面渲染类——mysurfaceview 498 17.9 六自由度关节 502 17.9.1 六自由度关节的基本知识 502 17.9.2 案例的运行效果 503 17.9.3 人偶类——doll 503 17.9.4 拾取时采用的点对点关节 505 17.10 本章小结 509 第18章 传感器应用的开发 510 18.1 基本的开发流程 510 18.2 加速度传感器 512 18.2.1 加速度传感器简介 513 18.2.2 案例的开发 514 18.3 磁场传感器 514 18.3.1 磁场传感器简介 514 18.3.2 案例的开发 514 18.4 光传感器 516 18.4.1 光传感器简介 516 18.4.2 案例的开发 516 18.5 温度传感器 518 18.5.1 温度传感器简介 518 18.5.2 案例的开发 518 18.6 接近传感器 519 18.6.1 接近传感器简介 519 18.6.2 案例的开发 520 18.7 姿态传感器 521 18.7.1 姿态传感器简介 521 18.7.2 案例的开发 522 18.8 本章小结 528 第19章 游戏开发小贴士 529 19.1 3d拾取技术 529 19.1.1 案例效果与基本原理 529 19.1.2 开发步骤 531 19.2 多点触控 537 19.2.1 案例效果与基本原理 537 19.2.2 开发步骤 538 19.3 多键监听 541 19.3.1 案例效果与基本原理 541 19.3.2 开发步骤 542 19.4 本章小结 544 第20章 bn赛艇 545 20.1 游戏背景及功能概述 545 20.1.1 背景概述 545 20.1.2 功能介绍 545 20.2 游戏的策划及准备工作 547 20.2.1 游戏的策划 547 20.2.2 android平台下游戏的准备工作 548 20.3 游戏的架构 552 20.3.1 各个类简要介绍 553 20.3.2 游戏框架简介 558 20.4 主控制类myactivity 559 20.5 2d界面相关类 563 20.5.1 欢迎界面类welcomeview 563 20.5.2 2d界面父类mysfview 565 20.5.3 主菜单类menuview 565 20.5.4 2d界面绘制类viewfordraw 566 20.5.5 数据库工具类dbutil 568 20.5.6 android系统版本对话框androidversiondialog 570 20.6 选船界面相关类 570 20.6.1 着色器管理类shadermanager 571 20.6.2 围墙类colorlightrect 571 20.6.3 选船房间类housefordraw 573 20.6.4 展台类displaystation 575 20.6.5 赛艇类boat 576 20.6.6 选船界面xcsurfaceview 576 20.7 游戏界面相关类 582 20.7.1 进度条类process 583 20.7.2 3d物体父类bndrawer 584 20.7.3 3d物体控制类tdobjectforcontrol 584 20.7.4 赛艇类boat 585 20.7.5 可碰撞物体父类kzbjdrawer 586 20.7.6 可碰撞物体控制类kzbjforcontr
      本书共分两篇,第一篇介绍了Android 3D游戏开发的基础知识,主要对OpenGL ES的相关内容进行了介绍。   章 名主 要 内 容   第1章 英雄还看今朝—Android简介本章介绍了市场上主流的手机平台,同时也分析了未来手机平台的发展趋势及Android平台的前景   第2章 数风流人物—当前流行游戏类型简介本章以分类的方式简要地介绍了当前流行的游戏的玩法,游戏的视觉效果,游戏的设计及《仙剑》等著名游戏的历史   第3章 不积跬步,无以至千里—游戏开发基础知识本章初步介绍了游戏开发的基础知识   第4章 千里之行,始于足下—3D开发基础知识本章介绍了3D开发中的基础知识,包括OpenGL ES的介绍及OpenGL ES中绘制模型的原理,并通过点、线和三角形的绘制介绍了OpenGL ES中模型的几种绘制方式。最后介绍了3D场景中常用的两种投影方式,并通过例子比较了这两种投影的区别   第5章 愿君多采撷,此物最相思—光照效果的开发本章介绍了光照的基础知识,包括环境光、散射光及镜面光   第6章 为伊消得人憔悴——纹理映射本章主要介绍了纹理的基础知识,以及纹理的不同拉伸方式和纹理过滤高级技术,从绘制三角形开始到绘制地月系,可能会经历很长时间,但是这对以后的学习是有帮助的   第7章 海阔凭鱼跃,天高任鸟飞—3D基本形状的构建在本章中介绍了圆柱体、圆锥体、圆环、抛物面、双曲面和螺旋面在OpenGL ES中的渲染方法。这些基本形状在3D世界中应用广泛,在构造一些复杂物体时,经常会运用这些基本形状来进行拼装组合   第8章 执子之手,与子偕老—坐标变换本章介绍了坐标变换的应用。绘制3D场景的过程,主要是旋转和平移操作的组合,通过合理的堆栈操作,就比较容易绘制出所需的3D场景   第9章 孤帆远影碧空尽—摄像机与雾特效在本章中,首先对摄像机及其配置做了介绍。摄像机在3D编程中至关重要,没有正确的配置,摄像机可能不能获得想要的场景效果。然后对雾特效做了具体介绍,应用雾特效可以使场景更加逼真,并且可以减少场景渲染量来提高性能   第10章 假作真时真亦假—混合本章主要为读者介绍了混合,从混合的背景知识到如何配置源因子和目标因子。在介绍源因子和目标因子的时候,向读者介绍了一些预定义常量和一些常用的组合方式,以及如何启用混合   第11章 蓦然回首,那人却在灯火阑珊处—3D高级技术本章主要为读者介绍了3D的一部分高级技术。每一项技术通过讲解其原理和案例,使读者对3D高级技术有一定的了解   第12章 心有灵犀一点通—传感器在本章中,向读者介绍了Android中传感器的相关知识。包括传感器的种类、配置,并且着重介绍了姿态传感器的应用   第13章 千锤万凿出深山—游戏中的数学与物理在本章中对3D游戏中可能会用到的数学及物理知识进行了简单的介绍,这在3D游戏开发中是相当重要的。游戏中的核心算法,基本上都要用到数学和物理知识。一款游戏的性能很大程度上取决于游戏设计的算法   第14章 山舞银蛇,原驰蜡象—AI基本理念本章主要介绍了AI、AI引擎的基本组成与设计,以及游戏AI中图的搜索和模糊逻辑,其中游戏AI中图的搜索为本章的重点。在本章中详细介绍了5种算法的原理与实现   第15章 独上高楼,望尽天涯路—开发小秘籍本章介绍了地图设计器、多键技术、虚拟键盘、查找表技术、状态机、AABB边界框、穿透效应、拾取技术,以及天空盒和天空穹在OpenGL ES中的应用 第二篇以7个比较大的案例来说明Android平台下3D游戏的开发流程,通过这7个案例的讲解,读者对3D游戏的开发将会有更深层次的理解。   章 名主 要 内 容   第16章 体育类游戏——《疯狂投篮》本章介绍了Android 3D游戏《疯狂投篮》的开发。通过该案例向读者介绍了在Android平台下进行3D游戏开发的相关知识和基本流程,并对游戏开发中的编程技巧进行了介绍,并主要介绍了篮球与地面、墙面及篮框的碰撞检测及运动动画的实现方法   第17章 益智类游戏——《旋转积木》本章介绍了Android 3D游戏《旋转积木》的开发。主要介绍了积木旋转的不同状态的实现方法和地图设计器的应用   第18章 休闲类游戏——《摩天大楼》本章介绍了Android 3D游戏《摩天大楼》的开发。主要介绍了楼层与楼层之间的衔接与碰撞及掉落后翻转动画的实现   第19章 动作类游戏——《3D空战》本章介绍了Android 3D游戏《3D空战》的开发。主要介绍了飞机的构造方法和我方战机与敌方战机的操控及动画实现   第20章 桌面类游戏——《激情台球》本章介绍了Android 3D游戏《激情台球》的开发。主要介绍了台球与台球的碰撞检测实现、台球与球桌的碰撞检测实现和进球的判定实现   第21章 射击类游戏——《抢滩登陆》本章介绍了Android 3D游戏《抢滩登陆》的开发。主要运用了灰度图生成技术并且主要介绍了坦克运动的实现方法及炮弹碰撞检测的实现   第22章 竞技类游戏——《乡村飙车》本章介绍了Android 3D游戏《乡村飙车》的开发。主要介绍了运用分层绘制和拼接绘制的策略进行场景的优化绘制,并且对场景部件进行了分类控制   本书面向的读者   本书的内容详细,且几乎涵盖了Android 3D游戏开发所有相关的技术,并向读者介绍了真实项目的开发流程,主要面向以下读者。   Android的初学者   本书详细介绍了OpenGL ES的基础知识,并对Android 3D游戏程序的开发进行了介绍。作为一名Android的初学者,通过本书的学习可以快速全面地掌握Android 3D游戏开发的相关知识,稳健地步入Android 3D游戏开发人员的行列。   有一定Android基础且希望学习Android 3D游戏开发的读者   有一定Android基础的读者通过阅读本书的前半部分便可快速掌握OpenGL ES的基础知识,然后通过7个真实案例的学习迅速掌握Android平台下应用程序的开发。   在职的开发人员
      书名:《Android底层开发技术实战详解——内核、移植和驱动》(电子工业出版社.王振丽)。本书从底层原理开始讲起,结合真实的案例向读者详细介绍了android内核、移植和驱动开发的整个流程。全书分为19章,依次讲解驱动移植的必要性,何为hal层深入分析,goldfish、msm、map内核和驱动解析,显示系统、输入系统、振动器系统、音频系统、视频输出系统的驱动,openmax多媒体、多媒体插件框架,传感器、照相机、wi-fi、蓝牙、gps和电话系统等。在每一章中,重点介绍了与Android驱动开发相关的底层知识,并对Android源码进行了剖析。 本书适合Android研发人员及Android爱好者学习,也可以作为相关培训学校和大专院校相关专业的教学用书。 全书压缩打包成3部分,这是第1部分。 第1章 Android底层开发基础 1 1.1 什么是驱动 1 1.1.1 驱动程序的魅力 1 1.1.2 电脑中的驱动 2 1.1.3 手机中的驱动程序 2 1.2 开源还是不开源的问题 3 1.2.1 雾里看花的开源 3 1.2.2 从为什么选择java谈为什么不开源驱动程序 3 1.2.3 对驱动开发者来说是一把双刃剑 4 1.3 Android和Linux 4 1.3.1 Linux简介 5 1.3.2 Android和Linux的关系 5 1.4 简析Linux内核 8 1.4.1 内核的体系结构 8 1.4.2 和Android密切相关的Linux内核知识 10 1.5 分析Linux内核源代码很有必要 14 1.5.1 源代码目录结构 14 1.5.2 浏览源代码的工具 16 1.5.3 为什么用汇编语言编写内核代码 17 1.5.4 Linux内核的显著特性 18 1.5.5 学习Linux内核的方法 26 第2章 分析Android源代码 31 2.1 搭建Linux开发环境和工具 31 2.1.1 搭建Linux开发环境 31 2.1.2 设置环境变量 32 2.1.3 安装编译工具 32 2.2 获取Android源代码 33 2.3 分析并编译Android源代码 35 2.3.1 Android源代码的结构 35 2.3.2 编译Android源代码 40 2.3.3 运行Android源代码 42 2.3.4 实践演练——演示编译Android程序的两种方法 43 2.4 编译Android kernel 47 2.4.1 获取goldfish内核代码 47 2.4.2 获取msm内核代码 50 2.4.3 获取omap内核代码 50 2.4.4 编译Android的Linux内核 50 2.5 运行模拟器 52 2.5.1 Linux环境下运行模拟器的方法 53 2.5.2 模拟器辅助工具——adb 54 第3章 驱动需要移植 57 3.1 驱动开发需要做的工作 57 3.2 Android移植 59 3.2.1 移植的任务 60 3.2.2 移植的内容 60 3.2.3 驱动开发的任务 61 3.3 Android对Linux的改造 61 3.3.1 Android对Linux内核文件的改动 62 3.3.2 为Android构建 Linux的操作系统 63 3.4 内核空间和用户空间接口是一个媒介 64 3.4.1 内核空间和用户空间的相互作用 64 3.4.2 系统和硬件之间的交互 64 3.4.3 使用relay实现内核到用户空间的数据传输 66 3.5 三类驱动程序 70 3.5.1 字符设备驱动程序 70 3.5.2 块设备驱动程序 79 3.5.3 网络设备驱动程序 82 第4章 hal层深入分析 84 4.1 认识hal层 84 4.1.1 hal层的发展 84 4.1.2 过去和现在的区别 86 4.2 分析hal层源代码 86 4.2.1 分析hal moudle 86 4.2.2 分析mokoid工程 89 4.3 总结hal层的使用方法 98 4.4 传感器在hal层的表现 101 4.4.1 hal层的sensor代码 102 4.4.2 总结sensor编程的流程 104 4.4.3 分析sensor源代码看Android api 与硬件平台的衔接 104 4.5 移植总结 116 4.5.1 移植各个Android部件的方式 116 4.5.2 移植技巧之一——不得不说的辅助工作 117 第5章 goldfish下的驱动解析 125 5.1 staging驱动 125 5.1.1 staging驱动概述 125 5.1.2 binder驱动程序 126 5.1.3 logger驱动程序 135 5.1.4 lowmemorykiller组件 136 5.1.5 timed output驱动程序 137 5.1.6 timed gpio驱动程序 139 5.1.7 ram console驱动程序 139 5.2 wakelock和early_suspend 140 5.2.1 wakelock和early_suspend的原理 140 5.2.2 Android休眠 141 5.2.3 Android唤醒 144 5.3 ashmem驱动程序 145 5.4 pmem驱动程序 148 5.5 alarm驱动程序 149 5.5.1 alarm简析 149 5.5.2 alarm驱动程序的实现 150 5.6 usb gadget驱动程序151 5.7 Android paranoid驱动程序153 5.8 goldfish设备驱动154 5.8.1 framebuffer驱动155 5.8.2 键盘驱动159 5.8.3 实时时钟驱动程序160 5.8.4 tty终端驱动程序161 5.8.5 nandflash驱动程序162 5.8.6 mmc驱动程序162 5.8.7 电池驱动程序162 第6章 msm内核和驱动解析164 6.1 msm基础164 6.1.1 常见msm处理器产品164 6.1.2 snapdragon内核介绍165 6.2 移植msm内核简介166 6.3 移植msm168 6.3.1 makefile文件168 6.3.2 驱动和组件170 6.3.3 设备驱动172 6.3.4 高通特有的组件174 第7章 omap内核和驱动解析177 7.1 omap基础177 7.1.1 omap简析177 7.1.2 常见omap处理器产品177 7.1.3 开发平台178 7.2 omap内核178 7.3 移植omap体系结构180 7.3.1 移植omap平台180 7.3.2 移植omap处理器183 7.4 移植Android专用驱动和组件188 7.5 omap的设备驱动190 第8章 显示系统驱动应用195 8.1 显示系统介绍195 8.1.1 Android的版本195 8.1.2 不同版本的显示系统195 8.2 移植和调试前的准备196 8.2.1 framebuffer驱动程序196 8.2.2 硬件抽象层198 8.3 实现显示系统的驱动程序210 8.3.1 goldfish中的framebuffer驱动程序210 8.3.2 使用gralloc模块的驱动程序214 8.4 msm高通处理器中的显示驱动实现224 8.4.1 msm中的framebuffer驱动程序225 8.4.2 msm中的gralloc驱动程序227 8.5 omap处理器中的显示驱动实现235 第9章 输入系统驱动应用239 9.1 输入系统介绍239 9.1.1 Android输入系统结构元素介绍239 9.1.2 移植Android输入系统时的工作240 9.2 input(输入)驱动241 9.3 模拟器的输入驱动256 9.4 msm高通处理器中的输入驱动实现257 9.4.1 触摸屏驱动257 9.4.2 按键和轨迹球驱动264 9.5 omap处理器平台中的输入驱动实现266 9.5.1 触摸屏驱动267 9.5.2 键盘驱动267 第10章 振动器系统驱动269 10.1 振动器系统结构269 10.1.1 硬件抽象层271 10.1.2 jni框架部分272 10.2 开始移植273 10.2.1 移植振动器驱动程序273 10.2.2 实现硬件抽象层274 10.3 在msm平台实现振动器驱动275 第11章 音频系统驱动279 11.1 音频系统结构279 11.2 分析音频系统的层次280 11.2.1 层次说明280 11.2.2 media库中的audio框架281 11.2.3 本地代码284 11.2.4 jni代码288 11.2.5 java代码289 11.3 移植audio系统的必备技术289 11.3.1 移植audio系统所要做的工作289 11.3.2 分析硬件抽象层290 11.3.3 分析audioflinger中的audio硬件抽象层的实现291 11.4 真正实现audio硬件抽象层298 11.5 msm平台实现audio驱动系统298 11.5.1 实现audio驱动程序298 11.5.2 实现硬件抽象层299 11.6 oss平台实现audio驱动系统304 11.6.1 oss驱动程序介绍304 11.6.2 mixer305 11.7 alsa平台实现audio系统312 11.7.1 注册音频设备和音频驱动312 11.7.2 在Android中使用alsa声卡313 11.7.3 在omap平台移植Android的alsa声卡驱动322 第12章 视频输出系统驱动326 12.1 视频输出系统结构326 12.2 需要移植的部分328 12.3 分析硬件抽象层328 12.3.1 overlay系统硬件抽象层的接口328 12.3.2 实现overlay系统的硬件抽象层331 12.3.3 实现接口332 12.4 实现overlay硬件抽象层333 12.5 在omap平台实现overlay系统335 12.5.1 实现输出视频驱动程序335 12.5.2 实现overlay硬件抽象层337 12.6 系统层调用overlay hal的架构342 12.6.1 调用overlay hal的架构的流程342 12.6.2 s3c6410 Android overlay的测试代码346 第13章 openmax多媒体框架349 13.1 openmax基本层次结构349 13.2 分析openmax框架构成350 13.2.1 openmax总体层次结构350 13.2.2 openmax il层的结构351 13.2.3 Android中的openmax354 13.3 实现openmax il层接口354 13.3.1 openmax il层的接口354 13.3.2 在openmax il层中需要做什么361 13.3.3 研究Android中的openmax适配层361 13.4 在omap平台实现openmax il363 13.4.1 实现文件364 13.4.2 分析ti openmax il的核心365 13.4.3 实现ti openmax il组件实例368 第14章 多媒体插件框架373 14.1 Android多媒体插件373 14.2 需要移植的内容374 14.3 opencore引擎375 14.3.1 opencore层次结构375 14.3.2 opencore代码结构376 14.3.3 opencore编译结构377 14.3.4 opencore oscl381 14.3.5 实现opencore中的openmax部分383 14.3.6 opencore的扩展398 14.4 stagefright引擎404 14.4.1 stagefright代码结构404 14.4.2 stagefright实现openmax接口405 14.4.3 video buffer传输流程409 第15章 传感器系统415 15.1 传感器系统的结构415 15.2 需要移植的内容417 15.2.1 移植驱动程序417 15.2.2 移植硬件抽象层418 15.2.3 实现上层部分419 15.3 在模拟器中实现传感器424 第16章 照相机系统430 16.1 camera系统的结构430 16.2 需要移植的内容433 16.3 移植和调试433 16.3.1 v4l2驱动程序433 16.3.2 硬件抽象层441 16.4 实现camera系统的硬件抽象层446 16.4.1 java程序部分446 16.4.2 camera的java本地调用部分447 16.4.3 camera的本地库libui.so448 16.4.4 camera服务libcameraservice.so449 16.5 msm平台实现camera系统454 16.6 omap平台实现camera系统457 第17章 wi-fi系统、蓝牙系统和gps系统459 17.1 wi-fi系统459 17.1.1 wi-fi系统的结构459 17.1.2 需要移植的内容461 17.1.3 移植和调试461 17.1.4 omap平台实现wi-fi469 17.1.5 配置wi-fi的流程471 17.1.6 具体演练——在Android下实现ethernet473 17.2 蓝牙系统475 17.2.1 蓝牙系统的结构475 17.2.2 需要移植的内容477 17.2.3 具体移植478 17.2.4 msm平台的蓝牙驱动480 17.3 定位系统482 17.3.1 定位系统的结构483 17.3.2 需要移植的内容484 17.3.3 移植和调试484 第18章 电话系统498 18.1 电话系统基础498 18.1.1 电话系统简介498 18.1.2 电话系统结构500 18.2 需要移植的内容501 18.3 移植和调试502 18.3.1 驱动程序502 18.3.2 ril接口504 18.4 电话系统实现流程分析507 18.4.1 初始启动流程507 18.4.2 request流程509 18.4.3 response流程512 第19章 其他系统514 19.1 alarm警报器系统514 19.1.1 alarm系统的结构514 19.1.2 需要移植的内容515 19.1.3 移植和调试516 19.1.4 模拟器环境的具体实现518 19.1.5 msm平台实现alarm518 19.2 lights光系统519 19.2.1 lights光系统的结构520 19.2.2 需要移植的内容521 19.2.3 移植和调试521 19.2.4 msm平台实现光系统523 19.3 battery电池系统524 19.3.1 battery系统的结构524 19.3.2 需要移植的内容526 19.3.3 移植和调试526 19.3.4 在模拟器中实现电池系统529
      android studio安装 这学期选修了移动应用开发学安卓。 因为自己搭了梯子,干脆就用android studio作为学习的ide(其实是因为认识的小姐姐在eclipse上踩坑了)。 再加上上学期jsp的环境mac本机碰到很多问题,决定还是用as来安装。 没有想到安装a... Execution failed for task ':app:checkDebugClasspath'. > Could not resolve all files for configuration ':app:debugCompileClasspath'. > Failed to transform file 'xxx.jar' to match attributes {artifactType=proce
      今天用android studio新建了一个项目,发现gradle这里转了半天没完成,后面还报错了。 ERROR: Unable to resolve dependency for ':app@debug/compileClasspath': Could not resolve androidx.appcompat:appcompat:1.1.0. 我以为是不是没连VPN所以下载很慢,但是发现...
      怀揣着对未来对希望,来到新公司当了一次接盘侠! 首先这个项目用到的友盟和微信全是不好用的,找的我沸腾了!最后发现开发平台的包名是错误的,或者包名和签名是反着的,具体因为什么我就不说了,改完就算了! 然后我前几天一直在改累积项目的问题。突然有一天bug改完了,写新需求,一引包发现app@debug/compileClasspath错误,然后开始的时候寻思是包冲突了也不太像啊,然后百度说我被墙了...
      Android应用程序进程(Application Process)是指Android应用程序从开发到上架的整个流程,它涉及从概念到设计,从开发到发布的各个步骤。 首先,Android应用程序开发者需要设计应用程序的功能,并确定程序的目标,然后制定应用程序的架构,并设计用户界面。其次,Android应用程序开发者需要使用Android SDK开发应用程序,并使用Android NDK实现更多的功能。 接着,Android应用程序开发者需要编译应用程序,并使用Android Debug Bridge(ADB)进行调试,以确保应用程序的稳定性和可用性。 最后,Android应用程序开发者需要将应用程序上传到Google Play,并等待Google审核,一旦审核通过,应用程序就可以开始在Google Play上销售了。
 
推荐文章
满身肌肉的炒饭  ·  服务商和渠道商的区别 | 微信开放社区
8 月前
慷慨的蚂蚁  ·  从星期一而不是星期天开始antd (datepicker)周-腾讯云开发者社区-腾讯云
1 年前
无邪的消炎药  ·  PyQt5滑块控制灰度图的二值化范围_qt 滑动调节二值化-CSDN博客
1 年前
重情义的蟠桃  ·  file.delete()返回true,但是文件没有删除_艾斯-李的博客-CSDN博客
1 年前
忐忑的显示器  ·  django模型的crud操作 - 夜间独行的浪子 - 博客园
1 年前
今天看啥   ·   Py中国   ·   codingpro   ·   小百科   ·   link之家   ·   卧龙AI搜索
删除内容请联系邮箱 2879853325@qq.com
Code - 代码工具平台
© 2024 ~ 沪ICP备11025650号