aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/AidlGenerator.java530
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/JavaGenerator.java300
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/builders/BaseBuilder.java4
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/builders/PreCompilerBuilder.java516
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/builders/PreCompilerDeltaVisitor.java178
-rw-r--r--testapps/basicProjectWithAidl/.classpath7
-rw-r--r--testapps/basicProjectWithAidl/.project33
-rw-r--r--testapps/basicProjectWithAidl/AndroidManifest.xml15
-rw-r--r--testapps/basicProjectWithAidl/build.properties17
-rw-r--r--testapps/basicProjectWithAidl/build.xml84
-rw-r--r--testapps/basicProjectWithAidl/default.properties12
-rw-r--r--testapps/basicProjectWithAidl/res/drawable/icon.pngbin0 -> 2574 bytes
-rw-r--r--testapps/basicProjectWithAidl/res/layout/main.xml13
-rw-r--r--testapps/basicProjectWithAidl/res/values/strings.xml4
-rw-r--r--testapps/basicProjectWithAidl/src/com/android/tests/basicprojectwithaidl/ITest.aidl7
-rw-r--r--testapps/basicProjectWithAidl/src/com/android/tests/basicprojectwithaidl/Main.java15
-rw-r--r--testapps/basicProjectWithAidl/src/com/android/tests/basicprojectwithaidl/Rect.aidl5
-rw-r--r--testapps/basicProjectWithAidl/src/com/android/tests/basicprojectwithaidl/Rect.java52
18 files changed, 1180 insertions, 612 deletions
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/AidlGenerator.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/AidlGenerator.java
new file mode 100644
index 0000000..e28cc12
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/AidlGenerator.java
@@ -0,0 +1,530 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Eclipse Public License, Version 1.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.eclipse.org/org/documents/epl-v10.php
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.ide.eclipse.adt.internal.build;
+
+import com.android.ide.eclipse.adt.AdtPlugin;
+import com.android.ide.eclipse.adt.AndroidConstants;
+import com.android.ide.eclipse.adt.internal.build.builders.BaseBuilder;
+import com.android.ide.eclipse.adt.internal.preferences.AdtPrefs;
+import com.android.ide.eclipse.adt.internal.preferences.AdtPrefs.BuildVerbosity;
+import com.android.ide.eclipse.adt.internal.project.BaseProjectHelper;
+import com.android.ide.eclipse.adt.internal.project.ProjectHelper;
+import com.android.sdklib.IAndroidTarget;
+
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IResourceDelta;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.SubProgressMonitor;
+import org.eclipse.jdt.core.IJavaProject;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * A {@link JavaGenerator} for aidl files.
+ *
+ */
+public class AidlGenerator extends JavaGenerator {
+
+ private static final String PROPERTY_COMPILE_AIDL = "compileAidl"; //$NON-NLS-1$
+
+ /**
+ * Single line aidl error<br>
+ * "&lt;path&gt;:&lt;line&gt;: &lt;error&gt;"
+ * or
+ * "&lt;path&gt;:&lt;line&gt; &lt;error&gt;"
+ */
+ private static Pattern sAidlPattern1 = Pattern.compile("^(.+?):(\\d+):?\\s(.+)$"); //$NON-NLS-1$
+
+
+ private enum AidlType {
+ UNKNOWN, INTERFACE, PARCELABLE;
+ }
+
+ // See comment in #getAidlType()
+// private final static Pattern sParcelablePattern = Pattern.compile(
+// "^\\s*parcelable\\s+([a-zA-Z_][a-zA-Z0-9_]*)\\s*;\\s*$");
+//
+// private final static Pattern sInterfacePattern = Pattern.compile(
+// "^\\s*interface\\s+([a-zA-Z_][a-zA-Z0-9_]*)\\s*(?:\\{.*)?$");
+
+
+ /**
+ * The custom delta visitor for aidl files. Based on the base JavaGenerator's delta visitor.
+ */
+ public static class AidlGeneratorDeltaVisitor extends JavaGeneratorDeltaVisitor {
+
+ @Override
+ public void handleChangedNonJavaFile(IFolder currentSourceFolder, IFile file, int kind) {
+ // get the extension of the resource
+ String ext = file.getFileExtension();
+ if (AndroidConstants.EXT_AIDL.equalsIgnoreCase(ext)) {
+ // first check whether it's a regular file or a parcelable.
+ AidlType type = getAidlType(file);
+
+ if (type == AidlType.INTERFACE) {
+ if (kind == IResourceDelta.REMOVED) {
+ // we'll have to remove the generated file.
+ addFileToRemove(currentSourceFolder, file);
+ } else if (getForceCompile() == false) {
+ // add the aidl file to the list of file to (re)compile
+ addFileToCompile(currentSourceFolder, file);
+ }
+ } else {
+ // force recompilations of all Aidl Files.
+ setForceCompile();
+ //mAidlToCompile.clear();
+ }
+ }
+ }
+
+ @Override
+ public boolean handleChangedGeneratedJavaFile(IFolder currentSourceFolder, IFile file,
+ List<IPath> sourceFolders) {
+
+ String fileName = file.getName();
+ String[] segments = file.getFullPath().segments();
+
+ // Look for the source aidl file in all the source folders that would match this given
+ // java file.
+ String aidlFileName = fileName.replaceAll(AndroidConstants.RE_JAVA_EXT,
+ AndroidConstants.DOT_AIDL);
+
+ for (IPath sourceFolderPath : sourceFolders) {
+ // do not search in the current source folder as it is the 'gen' folder.
+ if (sourceFolderPath.equals(currentSourceFolder.getFullPath())) {
+ continue;
+ }
+
+ IFolder sourceFolder = getFolder(sourceFolderPath);
+ if (sourceFolder != null) {
+ // go recursively, segment by segment.
+ // index starts at 2 (0 is project, 1 is 'gen'
+ IFile sourceFile = findFile(sourceFolder, segments, 2, aidlFileName);
+
+ if (sourceFile != null) {
+ // found the source. add it to the list of files to compile
+ addFileToCompile(currentSourceFolder, sourceFile);
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+ }
+
+ public AidlGenerator(IJavaProject javaProject, IFolder genFolder) {
+ super(new AidlGeneratorDeltaVisitor(), genFolder);
+
+ IProject project = javaProject.getProject();
+
+ boolean mustCompileAidl = ProjectHelper.loadBooleanProperty(project,
+ PROPERTY_COMPILE_AIDL, true /*defaultValue*/);
+
+ // if we stored that we have to compile some aidl, we build the list that will compile them
+ // all
+ if (mustCompileAidl) {
+ ArrayList<IPath> sourceFolderPathList = BaseProjectHelper.getSourceClasspaths(
+ javaProject);
+
+ buildCompilationList(project, sourceFolderPathList);
+ }
+ }
+
+ @Override
+ public boolean compileFiles(BaseBuilder builder, IProject project, IAndroidTarget projectTarget,
+ List<IPath> sourceFolders, IProgressMonitor monitor) throws CoreException {
+ List<SourceData> toCompile = getToCompile();
+ List<SourceData> toRemove = getToRemove();
+
+ if (toCompile.size() == 0 && toRemove.size() == 0) {
+ return false;
+ }
+
+ // create the command line
+ String[] command = new String[4 + sourceFolders.size()];
+ int index = 0;
+ command[index++] = projectTarget.getPath(IAndroidTarget.AIDL);
+ command[index++] = "-p" + projectTarget.getPath(IAndroidTarget.ANDROID_AIDL);
+
+ // since the path are relative to the workspace and not the project itself, we need
+ // the workspace root.
+ IWorkspaceRoot wsRoot = ResourcesPlugin.getWorkspace().getRoot();
+ for (IPath p : sourceFolders) {
+ IFolder f = wsRoot.getFolder(p);
+ command[index++] = "-I" + f.getLocation().toOSString(); //$NON-NLS-1$
+ }
+
+ // list of files that have failed compilation.
+ List<SourceData> stillNeedCompilation = new ArrayList<SourceData>();
+
+ // if an aidl file is being removed before we managed to compile it, it'll be in
+ // both list. We *need* to remove it from the compile list or it'll never go away.
+ for (SourceData aidlFile : toRemove) {
+ int pos = toCompile.indexOf(aidlFile);
+ if (pos != -1) {
+ toCompile.remove(pos);
+ }
+ }
+
+ // loop until we've compile them all
+ for (SourceData aidlData : toCompile) {
+ // Remove the AIDL error markers from the aidl file
+ builder.removeMarkersFromFile(aidlData.sourceFile, AndroidConstants.MARKER_AIDL);
+
+ // get the path of the source file.
+ IPath sourcePath = aidlData.sourceFile.getLocation();
+ String osSourcePath = sourcePath.toOSString();
+
+ IFile javaFile = getGenDestinationFile(aidlData, true /*createFolders*/, monitor);
+
+ // finish to set the command line.
+ command[index] = osSourcePath;
+ command[index + 1] = javaFile.getLocation().toOSString();
+
+ // launch the process
+ if (execAidl(builder, project, command, aidlData.sourceFile) == false) {
+ // aidl failed. File should be marked. We add the file to the list
+ // of file that will need compilation again.
+ stillNeedCompilation.add(aidlData);
+
+ // and we move on to the next one.
+ continue;
+ }
+ }
+
+ // change the list to only contains the file that have failed compilation
+ toCompile.clear();
+ toCompile.addAll(stillNeedCompilation);
+
+ // Remove the java files created from aidl files that have been removed.
+ for (SourceData aidlData : toRemove) {
+ IFile javaFile = getGenDestinationFile(aidlData, false /*createFolders*/, monitor);
+ if (javaFile.exists()) {
+ // This confirms the java file was generated by the builder,
+ // we can delete the aidlFile.
+ javaFile.getLocation().toFile().delete();
+ }
+ }
+
+ toRemove.clear();
+
+ // store the build state. If there are any files that failed to compile, we will
+ // force a full aidl compile on the next project open. (unless a full compilation succeed
+ // before the project is closed/re-opened.)
+ saveState(project);
+
+ return true;
+ }
+
+ /**
+ * Execute the aidl command line, parse the output, and mark the aidl file
+ * with any reported errors.
+ * @param command the String array containing the command line to execute.
+ * @param file The IFile object representing the aidl file being
+ * compiled.
+ * @return false if the exec failed, and build needs to be aborted.
+ */
+ private boolean execAidl(BaseBuilder builder, IProject project, String[] command, IFile file) {
+ // do the exec
+ try {
+ if (AdtPrefs.getPrefs().getBuildVerbosity() == BuildVerbosity.VERBOSE) {
+ StringBuilder sb = new StringBuilder();
+ for (String c : command) {
+ sb.append(c);
+ sb.append(' ');
+ }
+ String cmd_line = sb.toString();
+ AdtPlugin.printToConsole(project, cmd_line);
+ }
+
+ Process p = Runtime.getRuntime().exec(command);
+
+ // list to store each line of stderr
+ ArrayList<String> results = new ArrayList<String>();
+
+ // get the output and return code from the process
+ int result = BuildHelper.grabProcessOutput(project, p, results);
+
+ // attempt to parse the error output
+ boolean error = parseAidlOutput(results, file);
+
+ // If the process failed and we couldn't parse the output
+ // we print a message, mark the project and exit
+ if (result != 0 && error == true) {
+ // display the message in the console.
+ AdtPlugin.printErrorToConsole(project, results.toArray());
+
+ // mark the project and exit
+ BaseProjectHelper.markResource(project, AndroidConstants.MARKER_ADT,
+ Messages.Unparsed_AIDL_Errors, IMarker.SEVERITY_ERROR);
+ return false;
+ }
+ } catch (IOException e) {
+ // mark the project and exit
+ String msg = String.format(Messages.AIDL_Exec_Error, command[0]);
+ BaseProjectHelper.markResource(project, AndroidConstants.MARKER_ADT, msg,
+ IMarker.SEVERITY_ERROR);
+ return false;
+ } catch (InterruptedException e) {
+ // mark the project and exit
+ String msg = String.format(Messages.AIDL_Exec_Error, command[0]);
+ BaseProjectHelper.markResource(project, AndroidConstants.MARKER_ADT, msg,
+ IMarker.SEVERITY_ERROR);
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Parse the output of aidl and mark the file with any errors.
+ * @param lines The output to parse.
+ * @param file The file to mark with error.
+ * @return true if the parsing failed, false if success.
+ */
+ private boolean parseAidlOutput(ArrayList<String> lines, IFile file) {
+ // nothing to parse? just return false;
+ if (lines.size() == 0) {
+ return false;
+ }
+
+ Matcher m;
+
+ for (int i = 0; i < lines.size(); i++) {
+ String p = lines.get(i);
+
+ m = sAidlPattern1.matcher(p);
+ if (m.matches()) {
+ // we can ignore group 1 which is the location since we already
+ // have a IFile object representing the aidl file.
+ String lineStr = m.group(2);
+ String msg = m.group(3);
+
+ // get the line number
+ int line = 0;
+ try {
+ line = Integer.parseInt(lineStr);
+ } catch (NumberFormatException e) {
+ // looks like the string we extracted wasn't a valid
+ // file number. Parsing failed and we return true
+ return true;
+ }
+
+ // mark the file
+ BaseProjectHelper.markResource(file, AndroidConstants.MARKER_AIDL, msg, line,
+ IMarker.SEVERITY_ERROR);
+
+ // success, go to the next line
+ continue;
+ }
+
+ // invalid line format, flag as error, and bail
+ return true;
+ }
+
+ return false;
+ }
+
+ @Override
+ public void saveState(IProject project) {
+ // TODO: Optimize by saving only the files that need compilation
+ ProjectHelper.saveStringProperty(project, PROPERTY_COMPILE_AIDL,
+ Boolean.toString(getToCompile().size() > 0));
+ }
+
+
+ /**
+ * Goes through the build paths and fills the list of aidl files to compile
+ * ({@link #mAidlToCompile}).
+ * @param project The project.
+ * @param sourceFolderPathList The list of source folder paths.
+ * @param genFolder the gen folder
+ */
+ @Override
+ protected void buildCompilationList(IProject project, List<IPath> sourceFolderPathList) {
+ IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
+ for (IPath sourceFolderPath : sourceFolderPathList) {
+ IFolder sourceFolder = root.getFolder(sourceFolderPath);
+ // we don't look in the 'gen' source folder as there will be no source in there.
+ if (sourceFolder.exists() && sourceFolder.equals(getGenFolder()) == false) {
+ scanFolderForAidl(sourceFolder, sourceFolder);
+ }
+ }
+ }
+
+ /**
+ * Returns the {@link IFile} handle to the destination file for a given aidl source file
+ * ({@link AidlData}).
+ * @param aidlData the data for the aidl source file.
+ * @param createFolders whether or not the parent folder of the destination should be created
+ * if it does not exist.
+ * @param monitor the progress monitor
+ * @return the handle to the destination file.
+ * @throws CoreException
+ */
+ private IFile getGenDestinationFile(SourceData aidlData, boolean createFolders,
+ IProgressMonitor monitor) throws CoreException {
+ // build the destination folder path.
+ // Use the path of the source file, except for the path leading to its source folder,
+ // and for the last segment which is the filename.
+ int segmentToSourceFolderCount = aidlData.sourceFolder.getFullPath().segmentCount();
+ IPath packagePath = aidlData.sourceFile.getFullPath().removeFirstSegments(
+ segmentToSourceFolderCount).removeLastSegments(1);
+ Path destinationPath = new Path(packagePath.toString());
+
+ // get an IFolder for this path. It's relative to the 'gen' folder already
+ IFolder destinationFolder = getGenFolder().getFolder(destinationPath);
+
+ // create it if needed.
+ if (destinationFolder.exists() == false && createFolders) {
+ createFolder(destinationFolder, monitor);
+ }
+
+ // Build the Java file name from the aidl name.
+ String javaName = aidlData.sourceFile.getName().replaceAll(AndroidConstants.RE_AIDL_EXT,
+ AndroidConstants.DOT_JAVA);
+
+ // get the resource for the java file.
+ IFile javaFile = destinationFolder.getFile(javaName);
+ return javaFile;
+ }
+
+ /**
+ * Scans a folder and fills the list of aidl files to compile.
+ * @param sourceFolder the root source folder.
+ * @param folder The folder to scan.
+ */
+ private void scanFolderForAidl(IFolder sourceFolder, IFolder folder) {
+ try {
+ IResource[] members = folder.members();
+ for (IResource r : members) {
+ // get the type of the resource
+ switch (r.getType()) {
+ case IResource.FILE:
+ // if this a file, check that the file actually exist
+ // and that it's an aidl file
+ if (r.exists() &&
+ AndroidConstants.EXT_AIDL.equalsIgnoreCase(r.getFileExtension())) {
+ addFileToCompile(sourceFolder, (IFile)r);
+ }
+ break;
+ case IResource.FOLDER:
+ // recursively go through children
+ scanFolderForAidl(sourceFolder, (IFolder)r);
+ break;
+ default:
+ // this would mean it's a project or the workspace root
+ // which is unlikely to happen. we do nothing
+ break;
+ }
+ }
+ } catch (CoreException e) {
+ // Couldn't get the members list for some reason. Just return.
+ }
+ }
+
+ /**
+ * Creates the destination folder. Because
+ * {@link IFolder#create(boolean, boolean, IProgressMonitor)} only works if the parent folder
+ * already exists, this goes and ensure that all the parent folders actually exist, or it
+ * creates them as well.
+ * @param destinationFolder The folder to create
+ * @param monitor the {@link IProgressMonitor},
+ * @throws CoreException
+ */
+ private void createFolder(IFolder destinationFolder, IProgressMonitor monitor)
+ throws CoreException {
+
+ // check the parent exist and create if necessary.
+ IContainer parent = destinationFolder.getParent();
+ if (parent.getType() == IResource.FOLDER && parent.exists() == false) {
+ createFolder((IFolder)parent, monitor);
+ }
+
+ // create the folder.
+ destinationFolder.create(true /*force*/, true /*local*/,
+ new SubProgressMonitor(monitor, 10));
+ }
+
+ /**
+ * Returns the type of the aidl file. Aidl files can either declare interfaces, or declare
+ * parcelables. This method will attempt to parse the file and return the type. If the type
+ * cannot be determined, then it will return {@link AidlType#UNKNOWN}.
+ * @param file The aidl file
+ * @return the type of the aidl.
+ */
+ private static AidlType getAidlType(IFile file) {
+ // At this time, parsing isn't available, so we return UNKNOWN. This will force
+ // a recompilation of all aidl file as soon as one is changed.
+ return AidlType.UNKNOWN;
+
+ // TODO: properly parse aidl file to determine type and generate dependency graphs.
+//
+// String className = file.getName().substring(0,
+// file.getName().length() - AndroidConstants.DOT_AIDL.length());
+//
+// InputStream input = file.getContents(true /* force*/);
+// try {
+// BufferedReader reader = new BufferedReader(new InputStreateader(input));
+// String line;
+// while ((line = reader.readLine()) != null) {
+// if (line.length() == 0) {
+// continue;
+// }
+//
+// Matcher m = sParcelablePattern.matcher(line);
+// if (m.matches() && m.group(1).equals(className)) {
+// return AidlType.PARCELABLE;
+// }
+//
+// m = sInterfacePattern.matcher(line);
+// if (m.matches() && m.group(1).equals(className)) {
+// return AidlType.INTERFACE;
+// }
+// }
+// } catch (IOException e) {
+// throw new CoreException(new Status(IStatus.ERROR, AdtPlugin.PLUGIN_ID,
+// "Error parsing aidl file", e));
+// } finally {
+// try {
+// input.close();
+// } catch (IOException e) {
+// throw new CoreException(new Status(IStatus.ERROR, AdtPlugin.PLUGIN_ID,
+// "Error parsing aidl file", e));
+// }
+// }
+//
+// return AidlType.UNKNOWN;
+ }
+
+
+}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/JavaGenerator.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/JavaGenerator.java
new file mode 100644
index 0000000..1f9244d
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/JavaGenerator.java
@@ -0,0 +1,300 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Eclipse Public License, Version 1.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.eclipse.org/org/documents/epl-v10.php
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.ide.eclipse.adt.internal.build;
+
+import com.android.ide.eclipse.adt.internal.build.builders.BaseBuilder;
+import com.android.sdklib.IAndroidTarget;
+
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Base class to handle generated java code.
+ *
+ * It provides management for modified source file list, deleted source file list, reconciliation
+ * of previous lists, storing the current state of the build.
+ *
+ * It also provides a base class for delta visitor that should be customized for each Generator
+ * extending this class.
+ *
+ */
+public abstract class JavaGenerator {
+
+ /**
+ * Data to temporarily store source file information.
+ */
+ protected static class SourceData {
+ IFile sourceFile;
+ /** this is the root source folder, not the file parent. */
+ IFolder sourceFolder;
+
+ SourceData(IFolder sourceFolder, IFile sourceFile) {
+ this.sourceFolder = sourceFolder;
+ this.sourceFile = sourceFile;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((sourceFile == null) ? 0 : sourceFile.hashCode());
+ result = prime * result + ((sourceFolder == null) ? 0 : sourceFolder.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ SourceData other = (SourceData) obj;
+ if (sourceFile == null) {
+ if (other.sourceFile != null)
+ return false;
+ } else if (!sourceFile.equals(other.sourceFile))
+ return false;
+ if (sourceFolder == null) {
+ if (other.sourceFolder != null)
+ return false;
+ } else if (!sourceFolder.equals(other.sourceFolder))
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ return "SourceData [sourceFile=" //$NON-NLS-1$
+ + sourceFile
+ + ", sourceFolder=" //$NON-NLS-1$
+ + sourceFolder
+ + "]"; //$NON-NLS-1$
+ }
+ }
+
+ /**
+ * Base delta visitor for the Java generator classes.
+ *
+ * It provides storage for modified and deleted source files and a few other features.
+ */
+ public abstract static class JavaGeneratorDeltaVisitor {
+
+ private IWorkspaceRoot mRoot;
+
+ private boolean mForceCompile;
+
+ /** List of source files found that are modified or new. */
+ private final List<SourceData> mToCompile = new ArrayList<SourceData>();
+
+ /** List of .aidl files that have been removed. */
+ private final List<SourceData> mToRemove = new ArrayList<SourceData>();
+
+ public abstract boolean handleChangedGeneratedJavaFile(IFolder currentSourceFolder,
+ IFile file, List<IPath> sourceFolders);
+
+ public abstract void handleChangedNonJavaFile(IFolder currentSourceFolder,
+ IFile file, int kind);
+
+ public void setWorkspaceRoot(IWorkspaceRoot root) {
+ mRoot = root;
+ }
+
+ public void setForceCompile() {
+ mForceCompile = true;
+ }
+
+ boolean getForceCompile() {
+ return mForceCompile;
+ }
+
+ public void addFileToCompile(IFolder sourceFolder, IFile sourceFile) {
+ mToCompile.add(new SourceData(sourceFolder, sourceFile));
+ }
+
+ List<SourceData> getFilesToCompile() {
+ return mToCompile;
+ }
+
+ public void addFileToRemove(IFolder sourceFolder, IFile sourceFile) {
+ mToRemove.add(new SourceData(sourceFolder, sourceFile));
+ }
+
+ List<SourceData> getFilesToRemove() {
+ return mToRemove;
+ }
+
+ public void reset() {
+ mForceCompile = false;
+ mToCompile.clear();
+ mToRemove.clear();
+ }
+
+ /**
+ * Returns a handle to the folder identified by the given path in this container.
+ * <p/>The different with {@link IContainer#getFolder(IPath)} is that this returns a non
+ * null object only if the resource actually exists and is a folder (and not a file)
+ * @param path the path of the folder to return.
+ * @return a handle to the folder if it exists, or null otherwise.
+ */
+ protected IFolder getFolder(IPath path) {
+ IResource resource = mRoot.findMember(path);
+ if (resource != null && resource.exists() && resource.getType() == IResource.FOLDER) {
+ return (IFolder)resource;
+ }
+
+ return null;
+ }
+
+ /**
+ * Searches for and return a file in a folder. The file is defined by its segments, and
+ * a new name (replacing the last segment).
+ * @param folder the folder we are searching
+ * @param segments the segments of the file to search.
+ * @param index the index of the current segment we are looking for
+ * @param filename the new name to replace the last segment.
+ * @return the {@link IFile} representing the searched file, or null if not found
+ */
+ protected IFile findFile(IFolder folder, String[] segments, int index, String filename) {
+ boolean lastSegment = index == segments.length - 1;
+ IResource resource = folder.findMember(lastSegment ? filename : segments[index]);
+ if (resource != null && resource.exists()) {
+ if (lastSegment) {
+ if (resource.getType() == IResource.FILE) {
+ return (IFile)resource;
+ }
+ } else {
+ if (resource.getType() == IResource.FOLDER) {
+ return findFile((IFolder)resource, segments, index+1, filename);
+ }
+ }
+ }
+ return null;
+ }
+ }
+
+ /** List of source files found that are modified or new. */
+ private final List<SourceData> mToCompile = new ArrayList<SourceData>();
+
+ /** List of .aidl files that have been removed. */
+ private final List<SourceData> mToRemove = new ArrayList<SourceData>();
+
+ private final JavaGeneratorDeltaVisitor mDeltaVisitor;
+
+ private final IFolder mGenFolder;
+
+ protected JavaGenerator(JavaGeneratorDeltaVisitor deltaVisitor, IFolder genFolder) {
+ mDeltaVisitor = deltaVisitor;
+ mGenFolder = genFolder;
+ }
+
+ public JavaGeneratorDeltaVisitor getDeltaVisitor() {
+ return mDeltaVisitor;
+ }
+
+ IFolder getGenFolder() {
+ return mGenFolder;
+ }
+
+ List<SourceData> getToCompile() {
+ return mToCompile;
+ }
+
+ List<SourceData> getToRemove() {
+ return mToRemove;
+ }
+
+ void addFileToCompile(IFolder sourceFolder, IFile sourceFile) {
+ mToCompile.add(new SourceData(sourceFolder, sourceFile));
+ }
+
+ public void prepareFullBuild(IProject project, List<IPath> sourceFolders) {
+ mDeltaVisitor.reset();
+ buildCompilationList(project, sourceFolders);
+ }
+
+ public void doneVisiting(IProject project, List<IPath> sourceFolders) {
+ if (mDeltaVisitor.getForceCompile()) {
+ buildCompilationList(project, sourceFolders);
+ } else {
+ // merge the previous file modification lists and the new one.
+ mergeFileModifications(mDeltaVisitor);
+ }
+
+ mDeltaVisitor.reset();
+
+ saveState(project);
+ }
+
+ protected abstract void buildCompilationList(IProject project, List<IPath> sourceFolders);
+
+ public abstract boolean compileFiles(BaseBuilder builder,
+ IProject project, IAndroidTarget projectTarget,
+ List<IPath> sourceFolders, IProgressMonitor monitor) throws CoreException;
+
+ public abstract void saveState(IProject project);
+
+ /**
+ * Merge the current list of source file to compile/remove with the one coming from the
+ * delta visitor
+ * @param visitor the delta visitor.
+ */
+ private void mergeFileModifications(JavaGeneratorDeltaVisitor visitor) {
+ List<SourceData> toRemove = visitor.getFilesToRemove();
+ List<SourceData> toCompile = visitor.getFilesToCompile();
+
+ // loop through the new toRemove list, and add it to the old one,
+ // plus remove any file that was still to compile and that are now
+ // removed
+ for (SourceData r : toRemove) {
+ if (mToRemove.indexOf(r) == -1) {
+ mToRemove.add(r);
+ }
+
+ int index = mToCompile.indexOf(r);
+ if (index != -1) {
+ mToCompile.remove(index);
+ }
+ }
+
+ // now loop through the new files to compile and add it to the list.
+ // Also look for them in the remove list, this would mean that they
+ // were removed, then added back, and we shouldn't remove them, just
+ // recompile them.
+ for (SourceData r : toCompile) {
+ if (mToCompile.indexOf(r) == -1) {
+ mToCompile.add(r);
+ }
+
+ int index = mToRemove.indexOf(r);
+ if (index != -1) {
+ mToRemove.remove(index);
+ }
+ }
+ }
+}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/builders/BaseBuilder.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/builders/BaseBuilder.java
index 553ec47..ee7756b 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/builders/BaseBuilder.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/builders/BaseBuilder.java
@@ -53,7 +53,7 @@ import javax.xml.parsers.SAXParserFactory;
* Base builder for XML files. This class allows for basic XML parsing with
* error checking and marking the files for errors/warnings.
*/
-abstract class BaseBuilder extends IncrementalProjectBuilder {
+public abstract class BaseBuilder extends IncrementalProjectBuilder {
/** SAX Parser factory. */
@@ -193,7 +193,7 @@ abstract class BaseBuilder extends IncrementalProjectBuilder {
* @param markerId The id of the markers to remove. If null, all marker of
* type <code>IMarker.PROBLEM</code> will be removed.
*/
- protected final void removeMarkersFromFile(IFile file, String markerId) {
+ public final void removeMarkersFromFile(IFile file, String markerId) {
try {
if (file.exists()) {
file.deleteMarkers(markerId, true, IResource.DEPTH_ZERO);
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/builders/PreCompilerBuilder.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/builders/PreCompilerBuilder.java
index 11712bf..586dca5 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/builders/PreCompilerBuilder.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/builders/PreCompilerBuilder.java
@@ -19,6 +19,8 @@ package com.android.ide.eclipse.adt.internal.build.builders;
import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.adt.AndroidConstants;
import com.android.ide.eclipse.adt.internal.build.AaptParser;
+import com.android.ide.eclipse.adt.internal.build.AidlGenerator;
+import com.android.ide.eclipse.adt.internal.build.JavaGenerator;
import com.android.ide.eclipse.adt.internal.build.Messages;
import com.android.ide.eclipse.adt.internal.preferences.AdtPrefs;
import com.android.ide.eclipse.adt.internal.preferences.AdtPrefs.BuildVerbosity;
@@ -37,20 +39,16 @@ import com.android.sdklib.SdkConstants;
import com.android.sdklib.xml.AndroidManifest;
import com.android.sdklib.xml.ManifestData;
-import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceDelta;
-import org.eclipse.core.resources.IWorkspaceRoot;
-import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Path;
-import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
@@ -58,8 +56,6 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
/**
* Pre Java Compiler.
@@ -80,42 +76,6 @@ public class PreCompilerBuilder extends BaseBuilder {
private static final String PROPERTY_PACKAGE = "manifestPackage"; //$NON-NLS-1$
private static final String PROPERTY_COMPILE_RESOURCES = "compileResources"; //$NON-NLS-1$
- private static final String PROPERTY_COMPILE_AIDL = "compileAidl"; //$NON-NLS-1$
-
- /**
- * Single line aidl error<br>
- * "&lt;path&gt;:&lt;line&gt;: &lt;error&gt;"
- * or
- * "&lt;path&gt;:&lt;line&gt; &lt;error&gt;"
- */
- private static Pattern sAidlPattern1 = Pattern.compile("^(.+?):(\\d+):?\\s(.+)$"); //$NON-NLS-1$
-
- /**
- * Data to temporarily store aidl source file information
- */
- static class AidlData {
- IFile aidlFile;
- IFolder sourceFolder;
-
- AidlData(IFolder sourceFolder, IFile aidlFile) {
- this.sourceFolder = sourceFolder;
- this.aidlFile = aidlFile;
- }
-
- @Override
- public boolean equals(Object obj) {
- if (this == obj) {
- return true;
- }
-
- if (obj instanceof AidlData) {
- AidlData file = (AidlData)obj;
- return aidlFile.equals(file.aidlFile) && sourceFolder.equals(file.sourceFolder);
- }
-
- return false;
- }
- }
/**
* Resource Compile flag. This flag is reset to false after each successful compilation, and
@@ -124,11 +84,7 @@ public class PreCompilerBuilder extends BaseBuilder {
*/
private boolean mMustCompileResources = false;
- /** List of .aidl files found that are modified or new. */
- private final ArrayList<AidlData> mAidlToCompile = new ArrayList<AidlData>();
-
- /** List of .aidl files that have been removed. */
- private final ArrayList<AidlData> mAidlToRemove = new ArrayList<AidlData>();
+ private final List<JavaGenerator> mGeneratorList = new ArrayList<JavaGenerator>();
/** cache of the java package defined in the manifest */
private String mManifestPackage;
@@ -144,6 +100,7 @@ public class PreCompilerBuilder extends BaseBuilder {
*/
private DerivedProgressMonitor mDerivedProgressMonitor;
+
/**
* Progress monitor waiting the end of the process to set a persistent value
* in a file. This is typically used in conjunction with <code>IResource.refresh()</code>,
@@ -153,17 +110,14 @@ public class PreCompilerBuilder extends BaseBuilder {
*/
private static class DerivedProgressMonitor implements IProgressMonitor {
private boolean mCancelled = false;
- private final ArrayList<IFile> mFileList = new ArrayList<IFile>();
private boolean mDone = false;
- public DerivedProgressMonitor() {
- }
+ private final IFolder mGenFolder;
- void addFile(IFile file) {
- mFileList.add(file);
+ public DerivedProgressMonitor(IFolder genFolder) {
+ mGenFolder = genFolder;
}
void reset() {
- mFileList.clear();
mDone = false;
}
@@ -173,14 +127,30 @@ public class PreCompilerBuilder extends BaseBuilder {
public void done() {
if (mDone == false) {
mDone = true;
- for (IFile file : mFileList) {
- if (file.exists()) {
- try {
- file.setDerived(true);
- } catch (CoreException e) {
- // This really shouldn't happen since we check that the resource exist.
- // Worst case scenario, the resource isn't marked as derived.
- }
+ processChildrenOf(mGenFolder);
+ }
+ }
+
+ private void processChildrenOf(IFolder folder) {
+ IResource[] list;
+ try {
+ list = folder.members();
+ } catch (CoreException e) {
+ return;
+ }
+
+ for (IResource member : list) {
+ if (member.exists()) {
+ if (member.getType() == IResource.FOLDER) {
+ processChildrenOf((IFolder) member);
+ }
+
+ try {
+ member.setDerived(true);
+ } catch (CoreException e) {
+ // This really shouldn't happen since we check that the resource
+ // exist.
+ // Worst case scenario, the resource isn't marked as derived.
}
}
}
@@ -260,7 +230,10 @@ public class PreCompilerBuilder extends BaseBuilder {
doClean(project, monitor);
mMustCompileResources = true;
- buildAidlCompilationList(project, sourceFolderPathList);
+
+ for (JavaGenerator generator : mGeneratorList) {
+ generator.prepareFullBuild(project, sourceFolderPathList);
+ }
} else {
AdtPlugin.printBuildToConsole(BuildVerbosity.VERBOSE, project,
Messages.Start_Inc_Pre_Compiler);
@@ -272,20 +245,18 @@ public class PreCompilerBuilder extends BaseBuilder {
IResourceDelta delta = getDelta(project);
if (delta == null) {
mMustCompileResources = true;
- buildAidlCompilationList(project, sourceFolderPathList);
+
+ for (JavaGenerator generator : mGeneratorList) {
+ generator.prepareFullBuild(project, sourceFolderPathList);
+ }
} else {
- dv = new PreCompilerDeltaVisitor(this, sourceFolderPathList);
+ dv = new PreCompilerDeltaVisitor(this, sourceFolderPathList, mGeneratorList);
delta.accept(dv);
// record the state
mMustCompileResources |= dv.getCompileResources();
-
- if (dv.getForceAidlCompile()) {
- buildAidlCompilationList(project, sourceFolderPathList);
- } else {
- // handle aidl modification, and update mMustCompileAidl
- mergeAidlFileModifications(dv.getAidlToCompile(),
- dv.getAidlToRemove());
+ for (JavaGenerator generator : mGeneratorList) {
+ generator.doneVisiting(project, sourceFolderPathList);
}
// get the java package from the visitor
@@ -496,7 +467,9 @@ public class PreCompilerBuilder extends BaseBuilder {
// force a clean
doClean(project, monitor);
mMustCompileResources = true;
- buildAidlCompilationList(project, sourceFolderPathList);
+ for (JavaGenerator generator : mGeneratorList) {
+ generator.prepareFullBuild(project, sourceFolderPathList);
+ }
saveProjectBooleanProperty(PROPERTY_COMPILE_RESOURCES , mMustCompileResources);
}
@@ -505,10 +478,14 @@ public class PreCompilerBuilder extends BaseBuilder {
handleResources(project, javaPackage, projectTarget, manifestFile, libProjects);
}
- // now handle the aidl stuff.
- boolean aidlStatus = handleAidl(projectTarget, sourceFolderPathList, monitor);
+ // run the Java generators
+ boolean generatorStatus = false;
+ for (JavaGenerator generator : mGeneratorList) {
+ generatorStatus |= generator.compileFiles(this,
+ project, projectTarget, sourceFolderPathList, monitor);
+ }
- if (aidlStatus == false && mMustCompileResources == false) {
+ if (generatorStatus == false && mMustCompileResources == false) {
AdtPlugin.printBuildToConsole(BuildVerbosity.VERBOSE, project,
Messages.Nothing_To_Compile);
}
@@ -551,8 +528,6 @@ public class PreCompilerBuilder extends BaseBuilder {
protected void startupOnInitialize() {
super.startupOnInitialize();
- mDerivedProgressMonitor = new DerivedProgressMonitor();
-
IProject project = getProject();
// load the previous IFolder and java package.
@@ -561,20 +536,16 @@ public class PreCompilerBuilder extends BaseBuilder {
// get the source folder in which all the Java files are created
mGenFolder = project.getFolder(SdkConstants.FD_GEN_SOURCES);
- // Load the current compile flags. We ask for true if not found to force a
- // recompile.
+ // Load the current compile flags. We ask for true if not found to force a recompile.
mMustCompileResources = loadProjectBooleanProperty(PROPERTY_COMPILE_RESOURCES, true);
- boolean mustCompileAidl = loadProjectBooleanProperty(PROPERTY_COMPILE_AIDL, true);
- // if we stored that we have to compile some aidl, we build the list that will compile them
- // all
- if (mustCompileAidl) {
- IJavaProject javaProject = JavaCore.create(project);
- ArrayList<IPath> sourceFolderPathList = BaseProjectHelper.getSourceClasspaths(
- javaProject);
+ IJavaProject javaProject = JavaCore.create(project);
- buildAidlCompilationList(project, sourceFolderPathList);
- }
+ // load the java generators
+ JavaGenerator aidlGenerator = new AidlGenerator(javaProject, mGenFolder);
+ mGeneratorList.add(aidlGenerator);
+
+ mDerivedProgressMonitor = new DerivedProgressMonitor(mGenFolder);
}
/**
@@ -671,16 +642,10 @@ public class PreCompilerBuilder extends BaseBuilder {
private void execAapt(IProject project, IAndroidTarget projectTarget, String osOutputPath,
String osResPath, String osManifestPath, IFolder packageFolder,
ArrayList<IFolder> libResFolders, String customJavaPackage) throws CoreException {
- // since the R.java file may be already existing in read-only
- // mode we need to make it readable so that aapt can overwrite it
- IFile rJavaFile = packageFolder.getFile(AndroidConstants.FN_RESOURCE_CLASS);
-
- // do the same for the Manifest.java class
- IFile manifestJavaFile = packageFolder.getFile(AndroidConstants.FN_MANIFEST_CLASS);
-
- // we actually need to delete the manifest.java as it may become empty and
+ // We actually need to delete the manifest.java as it may become empty and
// in this case aapt doesn't generate an empty one, but instead doesn't
// touch it.
+ IFile manifestJavaFile = packageFolder.getFile(AndroidConstants.FN_MANIFEST_CLASS);
manifestJavaFile.getLocation().toFile().delete();
// launch aapt: create the command line
@@ -788,11 +753,6 @@ public class PreCompilerBuilder extends BaseBuilder {
// if the return code was OK, we refresh the folder that
// contains R.java to force a java recompile.
if (execError == 0) {
- // now add the R.java/Manifest.java to the list of file to be marked
- // as derived.
- mDerivedProgressMonitor.addFile(rJavaFile);
- mDerivedProgressMonitor.addFile(manifestJavaFile);
-
// build has been done. reset the state of the builder
mMustCompileResources = false;
@@ -853,358 +813,4 @@ public class PreCompilerBuilder extends BaseBuilder {
// This IFolder may not reference an actual existing folder.
return mGenFolder.getFolder(packagePath);
}
-
- /**
- * Compiles aidl files into java. This will also removes old java files
- * created from aidl files that are now gone.
- * @param projectTarget Target of the project
- * @param sourceFolders the list of source folders, relative to the workspace.
- * @param monitor the progress monitor
- * @returns true if it did something
- * @throws CoreException
- */
- private boolean handleAidl(IAndroidTarget projectTarget, ArrayList<IPath> sourceFolders,
- IProgressMonitor monitor) throws CoreException {
- if (mAidlToCompile.size() == 0 && mAidlToRemove.size() == 0) {
- return false;
- }
-
- // create the command line
- String[] command = new String[4 + sourceFolders.size()];
- int index = 0;
- command[index++] = projectTarget.getPath(IAndroidTarget.AIDL);
- command[index++] = "-p" + Sdk.getCurrent().getTarget(getProject()).getPath( //$NON-NLS-1$
- IAndroidTarget.ANDROID_AIDL);
-
- // since the path are relative to the workspace and not the project itself, we need
- // the workspace root.
- IWorkspaceRoot wsRoot = ResourcesPlugin.getWorkspace().getRoot();
- for (IPath p : sourceFolders) {
- IFolder f = wsRoot.getFolder(p);
- command[index++] = "-I" + f.getLocation().toOSString(); //$NON-NLS-1$
- }
-
- // list of files that have failed compilation.
- ArrayList<AidlData> stillNeedCompilation = new ArrayList<AidlData>();
-
- // if an aidl file is being removed before we managed to compile it, it'll be in
- // both list. We *need* to remove it from the compile list or it'll never go away.
- for (AidlData aidlFile : mAidlToRemove) {
- int pos = mAidlToCompile.indexOf(aidlFile);
- if (pos != -1) {
- mAidlToCompile.remove(pos);
- }
- }
-
- // loop until we've compile them all
- for (AidlData aidlData : mAidlToCompile) {
- // Remove the AIDL error markers from the aidl file
- removeMarkersFromFile(aidlData.aidlFile, AndroidConstants.MARKER_AIDL);
-
- // get the path of the source file.
- IPath sourcePath = aidlData.aidlFile.getLocation();
- String osSourcePath = sourcePath.toOSString();
-
- IFile javaFile = getGenDestinationFile(aidlData, true /*createFolders*/, monitor);
-
- // finish to set the command line.
- command[index] = osSourcePath;
- command[index + 1] = javaFile.getLocation().toOSString();
-
- // launch the process
- if (execAidl(command, aidlData.aidlFile) == false) {
- // aidl failed. File should be marked. We add the file to the list
- // of file that will need compilation again.
- stillNeedCompilation.add(aidlData);
-
- // and we move on to the next one.
- continue;
- } else {
- // make sure the file will be marked as derived once we refresh the 'gen' source
- // folder.
- mDerivedProgressMonitor.addFile(javaFile);
- }
- }
-
- // change the list to only contains the file that have failed compilation
- mAidlToCompile.clear();
- mAidlToCompile.addAll(stillNeedCompilation);
-
- // Remove the java files created from aidl files that have been removed.
- for (AidlData aidlData : mAidlToRemove) {
- IFile javaFile = getGenDestinationFile(aidlData, false /*createFolders*/, monitor);
- if (javaFile.exists()) {
- // This confirms the java file was generated by the builder,
- // we can delete the aidlFile.
- javaFile.getLocation().toFile().delete();
- }
- }
-
- mAidlToRemove.clear();
-
- // store the build state. If there are any files that failed to compile, we will
- // force a full aidl compile on the next project open. (unless a full compilation succeed
- // before the project is closed/re-opened.)
- // TODO: Optimize by saving only the files that need compilation
- saveProjectBooleanProperty(PROPERTY_COMPILE_AIDL , mAidlToCompile.size() > 0);
-
- return true;
- }
-
- /**
- * Returns the {@link IFile} handle to the destination file for a given aidl source file
- * ({@link AidlData}).
- * @param aidlData the data for the aidl source file.
- * @param createFolders whether or not the parent folder of the destination should be created
- * if it does not exist.
- * @param monitor the progress monitor
- * @return the handle to the destination file.
- * @throws CoreException
- */
- private IFile getGenDestinationFile(AidlData aidlData, boolean createFolders,
- IProgressMonitor monitor) throws CoreException {
- // build the destination folder path.
- // Use the path of the source file, except for the path leading to its source folder,
- // and for the last segment which is the filename.
- int segmentToSourceFolderCount = aidlData.sourceFolder.getFullPath().segmentCount();
- IPath packagePath = aidlData.aidlFile.getFullPath().removeFirstSegments(
- segmentToSourceFolderCount).removeLastSegments(1);
- Path destinationPath = new Path(packagePath.toString());
-
- // get an IFolder for this path. It's relative to the 'gen' folder already
- IFolder destinationFolder = mGenFolder.getFolder(destinationPath);
-
- // create it if needed.
- if (destinationFolder.exists() == false && createFolders) {
- createFolder(destinationFolder, monitor);
- }
-
- // Build the Java file name from the aidl name.
- String javaName = aidlData.aidlFile.getName().replaceAll(AndroidConstants.RE_AIDL_EXT,
- AndroidConstants.DOT_JAVA);
-
- // get the resource for the java file.
- IFile javaFile = destinationFolder.getFile(javaName);
- return javaFile;
- }
-
- /**
- * Creates the destination folder. Because
- * {@link IFolder#create(boolean, boolean, IProgressMonitor)} only works if the parent folder
- * already exists, this goes and ensure that all the parent folders actually exist, or it
- * creates them as well.
- * @param destinationFolder The folder to create
- * @param monitor the {@link IProgressMonitor},
- * @throws CoreException
- */
- private void createFolder(IFolder destinationFolder, IProgressMonitor monitor)
- throws CoreException {
-
- // check the parent exist and create if necessary.
- IContainer parent = destinationFolder.getParent();
- if (parent.getType() == IResource.FOLDER && parent.exists() == false) {
- createFolder((IFolder)parent, monitor);
- }
-
- // create the folder.
- destinationFolder.create(true /*force*/, true /*local*/,
- new SubProgressMonitor(monitor, 10));
- }
-
- /**
- * Execute the aidl command line, parse the output, and mark the aidl file
- * with any reported errors.
- * @param command the String array containing the command line to execute.
- * @param file The IFile object representing the aidl file being
- * compiled.
- * @return false if the exec failed, and build needs to be aborted.
- */
- private boolean execAidl(String[] command, IFile file) {
- // do the exec
- try {
- if (AdtPrefs.getPrefs().getBuildVerbosity() == BuildVerbosity.VERBOSE) {
- StringBuilder sb = new StringBuilder();
- for (String c : command) {
- sb.append(c);
- sb.append(' ');
- }
- String cmd_line = sb.toString();
- AdtPlugin.printToConsole(getProject(), cmd_line);
- }
-
- Process p = Runtime.getRuntime().exec(command);
-
- // list to store each line of stderr
- ArrayList<String> results = new ArrayList<String>();
-
- // get the output and return code from the process
- int result = grabProcessOutput(p, results);
-
- // attempt to parse the error output
- boolean error = parseAidlOutput(results, file);
-
- // If the process failed and we couldn't parse the output
- // we print a message, mark the project and exit
- if (result != 0 && error == true) {
- // display the message in the console.
- AdtPlugin.printErrorToConsole(getProject(), results.toArray());
-
- // mark the project and exit
- markProject(AndroidConstants.MARKER_ADT, Messages.Unparsed_AIDL_Errors,
- IMarker.SEVERITY_ERROR);
- return false;
- }
- } catch (IOException e) {
- // mark the project and exit
- String msg = String.format(Messages.AIDL_Exec_Error, command[0]);
- markProject(AndroidConstants.MARKER_ADT, msg, IMarker.SEVERITY_ERROR);
- return false;
- } catch (InterruptedException e) {
- // mark the project and exit
- String msg = String.format(Messages.AIDL_Exec_Error, command[0]);
- markProject(AndroidConstants.MARKER_ADT, msg, IMarker.SEVERITY_ERROR);
- return false;
- }
-
- return true;
- }
-
- /**
- * Goes through the build paths and fills the list of aidl files to compile
- * ({@link #mAidlToCompile}).
- * @param project The project.
- * @param sourceFolderPathList The list of source folder paths.
- */
- private void buildAidlCompilationList(IProject project,
- ArrayList<IPath> sourceFolderPathList) {
- IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
- for (IPath sourceFolderPath : sourceFolderPathList) {
- IFolder sourceFolder = root.getFolder(sourceFolderPath);
- // we don't look in the 'gen' source folder as there will be no source in there.
- if (sourceFolder.exists() && sourceFolder.equals(mGenFolder) == false) {
- scanFolderForAidl(sourceFolder, sourceFolder);
- }
- }
- }
-
- /**
- * Scans a folder and fills the list of aidl files to compile.
- * @param sourceFolder the root source folder.
- * @param folder The folder to scan.
- */
- private void scanFolderForAidl(IFolder sourceFolder, IFolder folder) {
- try {
- IResource[] members = folder.members();
- for (IResource r : members) {
- // get the type of the resource
- switch (r.getType()) {
- case IResource.FILE:
- // if this a file, check that the file actually exist
- // and that it's an aidl file
- if (r.exists() &&
- AndroidConstants.EXT_AIDL.equalsIgnoreCase(r.getFileExtension())) {
- mAidlToCompile.add(new AidlData(sourceFolder, (IFile)r));
- }
- break;
- case IResource.FOLDER:
- // recursively go through children
- scanFolderForAidl(sourceFolder, (IFolder)r);
- break;
- default:
- // this would mean it's a project or the workspace root
- // which is unlikely to happen. we do nothing
- break;
- }
- }
- } catch (CoreException e) {
- // Couldn't get the members list for some reason. Just return.
- }
- }
-
-
- /**
- * Parse the output of aidl and mark the file with any errors.
- * @param lines The output to parse.
- * @param file The file to mark with error.
- * @return true if the parsing failed, false if success.
- */
- private boolean parseAidlOutput(ArrayList<String> lines, IFile file) {
- // nothing to parse? just return false;
- if (lines.size() == 0) {
- return false;
- }
-
- Matcher m;
-
- for (int i = 0; i < lines.size(); i++) {
- String p = lines.get(i);
-
- m = sAidlPattern1.matcher(p);
- if (m.matches()) {
- // we can ignore group 1 which is the location since we already
- // have a IFile object representing the aidl file.
- String lineStr = m.group(2);
- String msg = m.group(3);
-
- // get the line number
- int line = 0;
- try {
- line = Integer.parseInt(lineStr);
- } catch (NumberFormatException e) {
- // looks like the string we extracted wasn't a valid
- // file number. Parsing failed and we return true
- return true;
- }
-
- // mark the file
- BaseProjectHelper.markResource(file, AndroidConstants.MARKER_AIDL, msg, line,
- IMarker.SEVERITY_ERROR);
-
- // success, go to the next line
- continue;
- }
-
- // invalid line format, flag as error, and bail
- return true;
- }
-
- return false;
- }
-
- /**
- * Merge the current list of aidl file to compile/remove with the new one.
- * @param toCompile List of file to compile
- * @param toRemove List of file to remove
- */
- private void mergeAidlFileModifications(ArrayList<AidlData> toCompile,
- ArrayList<AidlData> toRemove) {
- // loop through the new toRemove list, and add it to the old one,
- // plus remove any file that was still to compile and that are now
- // removed
- for (AidlData r : toRemove) {
- if (mAidlToRemove.indexOf(r) == -1) {
- mAidlToRemove.add(r);
- }
-
- int index = mAidlToCompile.indexOf(r);
- if (index != -1) {
- mAidlToCompile.remove(index);
- }
- }
-
- // now loop through the new files to compile and add it to the list.
- // Also look for them in the remove list, this would mean that they
- // were removed, then added back, and we shouldn't remove them, just
- // recompile them.
- for (AidlData r : toCompile) {
- if (mAidlToCompile.indexOf(r) == -1) {
- mAidlToCompile.add(r);
- }
-
- int index = mAidlToRemove.indexOf(r);
- if (index != -1) {
- mAidlToRemove.remove(index);
- }
- }
- }
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/builders/PreCompilerDeltaVisitor.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/builders/PreCompilerDeltaVisitor.java
index 4776666..ed3f503 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/builders/PreCompilerDeltaVisitor.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/builders/PreCompilerDeltaVisitor.java
@@ -18,9 +18,10 @@ package com.android.ide.eclipse.adt.internal.build.builders;
import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.adt.AndroidConstants;
+import com.android.ide.eclipse.adt.internal.build.JavaGenerator;
import com.android.ide.eclipse.adt.internal.build.Messages;
+import com.android.ide.eclipse.adt.internal.build.JavaGenerator.JavaGeneratorDeltaVisitor;
import com.android.ide.eclipse.adt.internal.build.builders.BaseBuilder.BaseDeltaVisitor;
-import com.android.ide.eclipse.adt.internal.build.builders.PreCompilerBuilder.AidlData;
import com.android.ide.eclipse.adt.internal.preferences.AdtPrefs.BuildVerbosity;
import com.android.ide.eclipse.adt.internal.project.AndroidManifestHelper;
import com.android.ide.eclipse.adt.io.IFileWrapper;
@@ -39,6 +40,7 @@ import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import java.util.ArrayList;
+import java.util.List;
/**
* Resource Delta visitor for the pre-compiler.
@@ -56,16 +58,6 @@ import java.util.ArrayList;
class PreCompilerDeltaVisitor extends BaseDeltaVisitor implements
IResourceDeltaVisitor {
- private enum AidlType {
- UNKNOWN, INTERFACE, PARCELABLE;
- }
-
- // See comment in #getAidlType()
-// private final static Pattern sParcelablePattern = Pattern.compile(
-// "^\\s*parcelable\\s+([a-zA-Z_][a-zA-Z0-9_]*)\\s*;\\s*$");
-//
-// private final static Pattern sInterfacePattern = Pattern.compile(
-// "^\\s*interface\\s+([a-zA-Z_][a-zA-Z0-9_]*)\\s*(?:\\{.*)?$");
// Result fields.
/**
@@ -76,17 +68,6 @@ class PreCompilerDeltaVisitor extends BaseDeltaVisitor implements
*/
private boolean mCompileResources = false;
- /**
- * Aidl force recompilation flag. If true, we'll attempt to recompile all aidl files.
- */
- private boolean mForceAidlCompile = false;
-
- /** List of .aidl files found that are modified or new. */
- private final ArrayList<AidlData> mAidlToCompile = new ArrayList<AidlData>();
-
- /** List of .aidl files that have been removed. */
- private final ArrayList<AidlData> mAidlToRemove = new ArrayList<AidlData>();
-
/** Manifest check/parsing flag. */
private boolean mCheckedManifestXml = false;
@@ -109,34 +90,32 @@ class PreCompilerDeltaVisitor extends BaseDeltaVisitor implements
private IFolder mSourceFolder = null;
/** List of source folders. */
- private ArrayList<IPath> mSourceFolders;
+ private List<IPath> mSourceFolders;
private boolean mIsGenSourceFolder = false;
+ private final List<JavaGeneratorDeltaVisitor> mGeneratorDeltaVisitors =
+ new ArrayList<JavaGeneratorDeltaVisitor>();
private IWorkspaceRoot mRoot;
- public PreCompilerDeltaVisitor(BaseBuilder builder, ArrayList<IPath> sourceFolders) {
+
+ public PreCompilerDeltaVisitor(BaseBuilder builder, ArrayList<IPath> sourceFolders,
+ List<JavaGenerator> generators) {
super(builder);
mSourceFolders = sourceFolders;
mRoot = ResourcesPlugin.getWorkspace().getRoot();
+
+ for (JavaGenerator generator : generators) {
+ JavaGeneratorDeltaVisitor dv = generator.getDeltaVisitor();
+ dv.setWorkspaceRoot(mRoot);
+ mGeneratorDeltaVisitors.add(dv);
+ }
}
public boolean getCompileResources() {
return mCompileResources;
}
- public boolean getForceAidlCompile() {
- return mForceAidlCompile;
- }
-
- public ArrayList<AidlData> getAidlToCompile() {
- return mAidlToCompile;
- }
-
- public ArrayList<AidlData> getAidlToRemove() {
- return mAidlToRemove;
- }
-
/**
* Returns whether the manifest file was parsed/checked for error during the resource delta
* visiting.
@@ -296,28 +275,13 @@ class PreCompilerDeltaVisitor extends BaseDeltaVisitor implements
// we want a warning
outputWarning = true;
} else {
- // this has to be a Java file created from an aidl file.
- // Look for the source aidl file in all the source folders.
- String aidlFileName = fileName.replaceAll(AndroidConstants.RE_JAVA_EXT,
- AndroidConstants.DOT_AIDL);
-
- for (IPath sourceFolderPath : mSourceFolders) {
- // do not search in the current source folder as it is the 'gen' folder.
- if (sourceFolderPath.equals(mSourceFolder.getFullPath())) {
- continue;
- }
-
- IFolder sourceFolder = getFolder(sourceFolderPath);
- if (sourceFolder != null) {
- // go recursively, segment by segment.
- // index starts at 2 (0 is project, 1 is 'gen'
- IFile sourceFile = findFile(sourceFolder, segments, 2, aidlFileName);
-
- if (sourceFile != null) {
- // found the source. add it to the list of files to compile
- mAidlToCompile.add(new AidlData(sourceFolder, sourceFile));
+ // look to see if this java file was generated by a generator.
+ if (AndroidConstants.EXT_JAVA.equalsIgnoreCase(file.getFileExtension())) {
+ for (JavaGeneratorDeltaVisitor dv : mGeneratorDeltaVisitors) {
+ if (dv.handleChangedGeneratedJavaFile(
+ mSourceFolder, file, mSourceFolders)) {
outputWarning = true;
- break;
+ break; // there shouldn't be 2 generators that handles the same file.
}
}
}
@@ -337,27 +301,8 @@ class PreCompilerDeltaVisitor extends BaseDeltaVisitor implements
}
} else {
// this is another source folder.
- // We only care about aidl files being added/modified/removed.
-
- // get the extension of the resource
- String ext = resource.getFileExtension();
- if (AndroidConstants.EXT_AIDL.equalsIgnoreCase(ext)) {
- // first check whether it's a regular file or a parcelable.
- AidlType type = getAidlType(file);
-
- if (type == AidlType.INTERFACE) {
- if (kind == IResourceDelta.REMOVED) {
- // we'll have to remove the generated file.
- mAidlToRemove.add(new AidlData(mSourceFolder, file));
- } else if (mForceAidlCompile == false) {
- // add the aidl file to the list of file to (re)compile
- mAidlToCompile.add(new AidlData(mSourceFolder, file));
- }
- } else {
- // force recompilations of all Aidl Files.
- mForceAidlCompile = true;
- mAidlToCompile.clear();
- }
+ for (JavaGeneratorDeltaVisitor dv : mGeneratorDeltaVisitors) {
+ dv.handleChangedNonJavaFile(mSourceFolder, file, kind);
}
}
@@ -458,32 +403,6 @@ class PreCompilerDeltaVisitor extends BaseDeltaVisitor implements
}
/**
- * Searches for and return a file in a folder. The file is defined by its segments, and a new
- * name (replacing the last segment).
- * @param folder the folder we are searching
- * @param segments the segments of the file to search.
- * @param index the index of the current segment we are looking for
- * @param filename the new name to replace the last segment.
- * @return the {@link IFile} representing the searched file, or null if not found
- */
- private IFile findFile(IFolder folder, String[] segments, int index, String filename) {
- boolean lastSegment = index == segments.length - 1;
- IResource resource = folder.findMember(lastSegment ? filename : segments[index]);
- if (resource != null && resource.exists()) {
- if (lastSegment) {
- if (resource.getType() == IResource.FILE) {
- return (IFile)resource;
- }
- } else {
- if (resource.getType() == IResource.FOLDER) {
- return findFile((IFolder)resource, segments, index+1, filename);
- }
- }
- }
- return null;
- }
-
- /**
* Returns a handle to the folder identified by the given path in this container.
* <p/>The different with {@link IContainer#getFolder(IPath)} is that this returns a non
* null object only if the resource actually exists and is a folder (and not a file)
@@ -499,55 +418,4 @@ class PreCompilerDeltaVisitor extends BaseDeltaVisitor implements
return null;
}
- /**
- * Returns the type of the aidl file. Aidl files can either declare interfaces, or declare
- * parcelables. This method will attempt to parse the file and return the type. If the type
- * cannot be determined, then it will return {@link AidlType#UNKNOWN}.
- * @param file The aidl file
- * @return the type of the aidl.
- * @throws CoreException
- */
- private AidlType getAidlType(IFile file) throws CoreException {
- // At this time, parsing isn't available, so we return UNKNOWN. This will force
- // a recompilation of all aidl file as soon as one is changed.
- return AidlType.UNKNOWN;
-
- // TODO: properly parse aidl file to determine type and generate dependency graphs.
-//
-// String className = file.getName().substring(0,
-// file.getName().length() - AndroidConstants.DOT_AIDL.length());
-//
-// InputStream input = file.getContents(true /* force*/);
-// try {
-// BufferedReader reader = new BufferedReader(new InputStreamReader(input));
-// String line;
-// while ((line = reader.readLine()) != null) {
-// if (line.length() == 0) {
-// continue;
-// }
-//
-// Matcher m = sParcelablePattern.matcher(line);
-// if (m.matches() && m.group(1).equals(className)) {
-// return AidlType.PARCELABLE;
-// }
-//
-// m = sInterfacePattern.matcher(line);
-// if (m.matches() && m.group(1).equals(className)) {
-// return AidlType.INTERFACE;
-// }
-// }
-// } catch (IOException e) {
-// throw new CoreException(new Status(IStatus.ERROR, AdtPlugin.PLUGIN_ID,
-// "Error parsing aidl file", e));
-// } finally {
-// try {
-// input.close();
-// } catch (IOException e) {
-// throw new CoreException(new Status(IStatus.ERROR, AdtPlugin.PLUGIN_ID,
-// "Error parsing aidl file", e));
-// }
-// }
-//
-// return AidlType.UNKNOWN;
- }
}
diff --git a/testapps/basicProjectWithAidl/.classpath b/testapps/basicProjectWithAidl/.classpath
new file mode 100644
index 0000000..609aa00
--- /dev/null
+++ b/testapps/basicProjectWithAidl/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="src" path="gen"/>
+ <classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/testapps/basicProjectWithAidl/.project b/testapps/basicProjectWithAidl/.project
new file mode 100644
index 0000000..24ed854
--- /dev/null
+++ b/testapps/basicProjectWithAidl/.project
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>basicProjectWithAidl</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>com.android.ide.eclipse.adt.ApkBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>com.android.ide.eclipse.adt.AndroidNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
diff --git a/testapps/basicProjectWithAidl/AndroidManifest.xml b/testapps/basicProjectWithAidl/AndroidManifest.xml
new file mode 100644
index 0000000..4cf7553
--- /dev/null
+++ b/testapps/basicProjectWithAidl/AndroidManifest.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ android:versionCode="1"
+ android:versionName="1.0" package="com.android.tests.basicprojectwithaidl">
+ <application android:label="@string/app_name" android:icon="@drawable/icon">
+ <activity android:name="com.android.tests.basicprojectwithaidlwithaidl.Main"
+ android:label="@string/app_name">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+ <uses-sdk android:minSdkVersion="AOSP"/>
+</manifest>
diff --git a/testapps/basicProjectWithAidl/build.properties b/testapps/basicProjectWithAidl/build.properties
new file mode 100644
index 0000000..ee52d86
--- /dev/null
+++ b/testapps/basicProjectWithAidl/build.properties
@@ -0,0 +1,17 @@
+# This file is used to override default values used by the Ant build system.
+#
+# This file must be checked in Version Control Systems, as it is
+# integral to the build system of your project.
+
+# This file is only used by the Ant script.
+
+# You can use this to override default values such as
+# 'source.dir' for the location of your java source folder and
+# 'out.dir' for the location of your output folder.
+
+# You can also use it define how the release builds are signed by declaring
+# the following properties:
+# 'key.store' for the location of your keystore and
+# 'key.alias' for the name of the key to use.
+# The password will be asked during the build when you use the 'release' target.
+
diff --git a/testapps/basicProjectWithAidl/build.xml b/testapps/basicProjectWithAidl/build.xml
new file mode 100644
index 0000000..9983df5
--- /dev/null
+++ b/testapps/basicProjectWithAidl/build.xml
@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project name="basicProject" default="help">
+
+<!-- The local.properties file is created and updated by the 'android'
+ tool.
+ It contains the path to the SDK. It should *NOT* be checked into
+ Version Control Systems. -->
+ <property file="local.properties" />
+
+ <!-- The build.properties file can be created by you and is never touched
+ by the 'android' tool. This is the place to change some of the
+ default property values used by the Ant rules.
+ Here are some properties you may want to change/update:
+
+ source.dir
+ The name of the source directory. Default is 'src'.
+ out.dir
+ The name of the output directory. Default is 'bin'.
+
+ Properties related to the SDK location or the project target should
+ be updated using the 'android' tool with the 'update' action.
+
+ This file is an integral part of the build system for your
+ application and should be checked into Version Control Systems.
+
+ -->
+ <property file="build.properties" />
+
+ <!-- The default.properties file is created and updated by the 'android'
+ tool, as well as ADT.
+ This file is an integral part of the build system for your
+ application and should be checked into Version Control Systems. -->
+ <property file="default.properties" />
+
+ <!-- Custom Android task to deal with the project target, and import the
+ proper rules.
+ This requires ant 1.6.0 or above. -->
+ <path id="android.antlibs">
+ <pathelement path="${sdk.dir}/tools/lib/anttasks.jar" />
+ <pathelement path="${sdk.dir}/tools/lib/sdklib.jar" />
+ <pathelement path="${sdk.dir}/tools/lib/androidprefs.jar" />
+ </path>
+
+ <taskdef name="setup"
+ classname="com.android.ant.SetupTask"
+ classpathref="android.antlibs" />
+
+<!-- extension targets. Uncomment the ones where you want to do custom work
+ in between standard targets -->
+<!--
+ <target name="-pre-build">
+ </target>
+ <target name="-pre-compile">
+ </target>
+
+ [This is typically used for code obfuscation.
+ Compiled code location: ${out.classes.absolute.dir}
+ If this is not done in place, override ${out.dex.input.absolute.dir}]
+ <target name="-post-compile">
+ </target>
+-->
+
+
+ <!-- Execute the Android Setup task that will setup some properties
+ specific to the target, and import the build rules files.
+
+ The rules file is imported from
+ <SDK>/platforms/<target_platform>/ant/ant_rules_r#.xml
+
+ To customize existing targets, there are two options:
+ - Customize only one target:
+ - copy/paste the target into this file, *before* the
+ <setup> task.
+ - customize it to your needs.
+ - Customize the whole script.
+ - copy/paste the content of the rules files (minus the top node)
+ into this file, *after* the <setup> task
+ - disable the import of the rules by changing the setup task
+ below to <setup import="false" />.
+ - customize to your needs.
+ -->
+ <setup />
+
+</project>
diff --git a/testapps/basicProjectWithAidl/default.properties b/testapps/basicProjectWithAidl/default.properties
new file mode 100644
index 0000000..38db660
--- /dev/null
+++ b/testapps/basicProjectWithAidl/default.properties
@@ -0,0 +1,12 @@
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system use,
+# "build.properties", and override values to adapt the script to your
+# project structure.
+
+# Project target.
+target=android-AOSP
+proguard.config=../proguard.config
diff --git a/testapps/basicProjectWithAidl/res/drawable/icon.png b/testapps/basicProjectWithAidl/res/drawable/icon.png
new file mode 100644
index 0000000..a07c69f
--- /dev/null
+++ b/testapps/basicProjectWithAidl/res/drawable/icon.png
Binary files differ
diff --git a/testapps/basicProjectWithAidl/res/layout/main.xml b/testapps/basicProjectWithAidl/res/layout/main.xml
new file mode 100644
index 0000000..783e4a0
--- /dev/null
+++ b/testapps/basicProjectWithAidl/res/layout/main.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ >
+<TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="Basic Project"
+ />
+</LinearLayout>
+
diff --git a/testapps/basicProjectWithAidl/res/values/strings.xml b/testapps/basicProjectWithAidl/res/values/strings.xml
new file mode 100644
index 0000000..a7322d3
--- /dev/null
+++ b/testapps/basicProjectWithAidl/res/values/strings.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="app_name">basicProject</string>
+</resources>
diff --git a/testapps/basicProjectWithAidl/src/com/android/tests/basicprojectwithaidl/ITest.aidl b/testapps/basicProjectWithAidl/src/com/android/tests/basicprojectwithaidl/ITest.aidl
new file mode 100644
index 0000000..cb7a314
--- /dev/null
+++ b/testapps/basicProjectWithAidl/src/com/android/tests/basicprojectwithaidl/ITest.aidl
@@ -0,0 +1,7 @@
+package com.android.tests.basicprojectwithaidl;
+
+interface ITest {
+ Rect getRect();
+
+}
+
diff --git a/testapps/basicProjectWithAidl/src/com/android/tests/basicprojectwithaidl/Main.java b/testapps/basicProjectWithAidl/src/com/android/tests/basicprojectwithaidl/Main.java
new file mode 100644
index 0000000..eaed510
--- /dev/null
+++ b/testapps/basicProjectWithAidl/src/com/android/tests/basicprojectwithaidl/Main.java
@@ -0,0 +1,15 @@
+package com.android.tests.basicprojectwithaidl;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class Main extends Activity
+{
+ /** Called when the activity is first created. */
+ @Override
+ public void onCreate(Bundle savedInstanceState)
+ {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.main);
+ }
+}
diff --git a/testapps/basicProjectWithAidl/src/com/android/tests/basicprojectwithaidl/Rect.aidl b/testapps/basicProjectWithAidl/src/com/android/tests/basicprojectwithaidl/Rect.aidl
new file mode 100644
index 0000000..734cf77
--- /dev/null
+++ b/testapps/basicProjectWithAidl/src/com/android/tests/basicprojectwithaidl/Rect.aidl
@@ -0,0 +1,5 @@
+package com.android.tests.basicprojectwithaidl;
+
+// Declare Rect so AIDL can find it and knows that it implements
+// the parcelable protocol.
+parcelable Rect; \ No newline at end of file
diff --git a/testapps/basicProjectWithAidl/src/com/android/tests/basicprojectwithaidl/Rect.java b/testapps/basicProjectWithAidl/src/com/android/tests/basicprojectwithaidl/Rect.java
new file mode 100644
index 0000000..8e16926
--- /dev/null
+++ b/testapps/basicProjectWithAidl/src/com/android/tests/basicprojectwithaidl/Rect.java
@@ -0,0 +1,52 @@
+package com.android.tests.basicprojectwithaidl;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+public class Rect implements Parcelable {
+ public int left;
+ public int top;
+ public int right;
+ public int bottom;
+
+ public static final Parcelable.Creator<Rect> CREATOR = new Parcelable.Creator<Rect>() {
+ public Rect createFromParcel(Parcel in) {
+ return new Rect(in);
+ }
+
+ public Rect[] newArray(int size) {
+ return new Rect[size];
+ }
+ };
+
+ public Rect() {
+ }
+
+ private Rect(Parcel in) {
+ readFromParcel(in);
+ }
+
+ public void writeToParcel(Parcel out) {
+ out.writeInt(left);
+ out.writeInt(top);
+ out.writeInt(right);
+ out.writeInt(bottom);
+ }
+
+ public void readFromParcel(Parcel in) {
+ left = in.readInt();
+ top = in.readInt();
+ right = in.readInt();
+ bottom = in.readInt();
+ }
+
+ public int describeContents() {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ public void writeToParcel(Parcel arg0, int arg1) {
+ // TODO Auto-generated method stub
+
+ }
+}